Pimp vs bluebird vs Q vs rsvp vs then promise (v12)

Revision 12 of this benchmark created on


Description

Perf comparison between four promise/a+ spec implementations, namely:

  1. Bluebird (2.9.12)
  2. Pimp (0.2.3)
  3. Q (1.1.2)
  4. RSVP (latest - last checked: 3.0.17)

Preparation HTML

<!-- pimp.js -->
<script>
/*
 * @author Pimp.js: Mudit Ameta
 * @license https://github.com/zeusdeux/pimp/blob/master/LICENSE MIT
 * @author setImmediate: YuzuJS
 * @license https://github.com/YuzuJS/setImmediate/blob/master/LICENSE.txt
 */
//# sourceMappingURL=pimp.min.map
!function(n,e){"use strict";function t(n){return m[d]=r.apply(e,n),d++}function r(n){var t=[].slice.call(arguments,1);return function(){"function"==typeof n?n.apply(e,t):new Function(""+n)()}}function o(n){if(h)setTimeout(r(o,n),0);else{var e=m[n];if(e){h=!0;try{e()}finally{i(n),h=!1}}}}function i(n){delete m[n]}function c(){p=function(){var n=t(arguments);return process.nextTick(r(o,n)),n}}function u(){if(n.postMessage&&!n.importScripts){var e=!0,t=n.onmessage;return n.onmessage=function(){e=!1},n.postMessage("","*"),n.onmessage=t,e}}function a(){var e="setImmediate$"+Math.random()+"$",r=function(t){t.source===n&&"string"==typeof t.data&&0===t.data.indexOf(e)&&o(+t.data.slice(e.length))};n.addEventListener?n.addEventListener("message",r,!1):n.attachEvent("onmessage",r),p=function(){var r=t(arguments);return n.postMessage(e+r,"*"),r}}function s(){var n=new MessageChannel;n.port1.onmessage=function(n){var e=n.data;o(e)},p=function(){var e=t(arguments);return n.port2.postMessage(e),e}}function f(){var n=y.documentElement;p=function(){var e=t(arguments),r=y.createElement("script");return r.onreadystatechange=function(){o(e),r.onreadystatechange=null,n.removeChild(r),r=null},n.appendChild(r),e}}function l(){p=function(){var n=t(arguments);return setTimeout(r(o,n),0),n}}if(!n.setImmediate){var p,d=1,m={},h=!1,y=n.document,v=Object.getPrototypeOf&&Object.getPrototypeOf(n);v=v&&v.setTimeout?v:n,"[object process]"==={}.toString.call(n.process)?c():u()?a():n.MessageChannel?s():y&&"onreadystatechange"in y.createElement("script")?f():l(),v.setImmediate=p,v.clearImmediate=i}}(new Function("return this")()),function(n){"use strict";function e(n){function r(n){var e;null!==s&&(n.done||(e=s?n.onFulfilled:n.onRejected,e?t(function(){var t;try{t=e(a),n.resolve(t)}catch(r){n.reject(r)}}):(s?n.resolve:n.reject)(a),n.done=!0))}function o(){for(var n in f)r(f[n])}function i(n){if(null===s){if(n)if(l===n)c(new TypeError("Promise cannot resolve to itself"));else if(n.constructor&&"Promise"===n.constructor.name)n.then(i,c);else if("function"==typeof n||"object"==typeof n)try{var e=n.then;"function"==typeof e?u(e.bind(n),i,c):(s=!0,a=n)}catch(t){c(t)}else s=!0,a=n;else s=!0,a=n;o()}}function c(n){null===s&&(s=!1,a=n,o())}function u(n,e,t){var r=!1;try{n(function(n){r||(r=!0,e(n))},function(n){r||(r=!0,t(n))})}catch(o){r||(r=!0,t(o))}}var a,s=null,f=[],l=this;if("function"!=typeof n)return new TypeError("Promise constructor requires a function");try{n(i,c)}catch(p){c(p)}this.then=function(n,t){var o,i=new e(function(e,r){o={promise:i,onFulfilled:"function"==typeof n&&n,onRejected:"function"==typeof t&&t,resolve:e,reject:r,done:!1}});return r(o),f.push(o),i},this.inspect=function(){var n={};return null===s?n.state="pending":s?(n.state="fulfilled",n.value=a):(n.state="rejected",n.reason=a),n}}n.exports?n.exports=e:n.Pimp=e;var t;try{t=process.nextTick}catch(r){try{t=setImmediate}catch(r){t=function(n){window.setTimeout(function(){n()},0)}}}}("undefined"==typeof module?window:module),function(n){"use strict";function e(n,e,t){var r={isArray:function(){if(!(t instanceof Array))throw new SyntaxError(e+" needs to be passed an array");if(!t.length)throw new SyntaxError(e+" needs an array of length >= 1")},isFunc:function(){if(!(t instanceof Function))throw new SyntaxError(e+" needs to be passed a function to promisify")}};return r[n](),!0}var t;t="[object Window]"===n.toString()&&"undefined"==typeof require?n.Pimp:process.env.PIMP_BROWSER_TEST?n.exports:require("./pimp"),n.exports?n.exports=t:n.Pimp=t,t.prototype.catch=function(n){return this.then(function(n){return n},n)},t.prototype.finally=function(n){var e=this,r=function(r){var o=0,i=function(){return e};return"function"==typeof n&&(o=n(r)),t.cast(o).then(i,i)};return this.then(r,r)},t.resolve=function(n){return new t(function(e){e(n)})},t.reject=function(n){return new t(function(e,t){t(n)})},t.cast=function(n){return n instanceof t&&n.then?n:t.resolve(n)},t.all=function(n){return e("isArray","Pimp.all",n),new t(function(e,r){var o=0,i=[];for(var c in n)n.hasOwnProperty(c)&&(n[c].then||(n[c]=t.cast(n[c])),n[c].then(function(t){o++,i.push(t),n.length===o&&e(i)},function(n){r(n)}))})},t.allFail=function(n){return e("isArray","Pimp.allFail",n),new t(function(e,r){var o=0,i=[];for(var c in n)n.hasOwnProperty(c)&&(n[c].then||(n[c]=t.cast(n[c])),n[c].then(function(n){r(n)},function(t){o++,i.push(t),n.length===o&&e(i)}))})},t.race=function(n){return e("isArray","Pimp.race",n),new t(function(e,r){for(var o in n)n.hasOwnProperty(o)&&(n[o].then||(n[o]=t.cast(n[o])),n[o].then(function(n){e(n)},function(n){r(n)}))})},t.deferred=function(){var n={};return n.promise=new t(function(e,t){n.resolve=e,n.reject=t}),n.inspect=n.promise.inspect,n},t.denodeify=function(n){return e("isFunc","Pimp.denodeify",n),function(){var e=t.deferred(),r=function(n,t){n?e.reject(n):(t=arguments.length>2?[].slice.call(arguments,1):t,e.resolve(t))};return[].push.call(arguments,r),n.apply(this,arguments),e.promise}}}("undefined"==typeof module?window:module);
</script>

<!-- bluebird -->
<script src="//cdn.jsdelivr.net/bluebird/2.9.12/bluebird.min.js">
</script>

<!-- Q -->
<script src="//cdnjs.cloudflare.com/ajax/libs/q.js/1.1.2/q.min.js"></script>

<!-- RSVP -->
<script src="//rsvpjs-builds.s3.amazonaws.com/rsvp-latest.js"></script>

Test runner

Ready to run.

Testing in
TestOps/sec
Bluebird
// async test
var d = Promise.pending();
var code = 'pend' + Math.random();

function eventFunc(e) {
  if (e.data === code) {
    window.removeEventListener('message', eventFunc);
    d.fulfill();
  }
}

d.promise.then(function() {
  deferred.resolve()
});
window.addEventListener('message', eventFunc);
window.postMessage(code, '*');
ready
Pimp
// async test
var d = Pimp.deferred()
var code = 'pimp' + Math.random();

function eventFunc(e) {
  if (e.data === code) {
    window.removeEventListener('message', eventFunc);
    d.resolve();
  }
}
window.addEventListener('message', eventFunc);
d.promise.then(function() {
  deferred.resolve()
})
window.postMessage(code, '*');
ready
Q
// async test
var d = Q.defer()
var code = 'q' + Math.random();

function eventFunc(e) {
  if (e.data === code) {
    window.removeEventListener('message', eventFunc);
    d.resolve();
  }
}
window.addEventListener('message', eventFunc);
d.promise.then(function() {
  deferred.resolve()
})
window.postMessage(code, '*');
ready
RSVP
// async test
var d = RSVP.defer();
var code = 'rsvp' + Math.random();

function eventFunc(e) {
  if (e.data === code) {
    window.removeEventListener('message', eventFunc);
    d.resolve();
  }
}
window.addEventListener('message', eventFunc);
d.promise.then(function() {
  deferred.resolve()
})
window.postMessage(code, '*');
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.