function MakePromise (asap) { function Promise(fn) { if (typeof this !== 'object' || typeof fn !== 'function') throw new TypeError(); this._state = null; this._value = null; this._deferreds = [] doResolve(fn, resolve.bind(this), reject.bind(this)); } function handle(deferred) { var me = this; if (this._state === null) { this._deferreds.push(deferred); return } asap(function() { var cb = me._state ? deferred.onFulfilled : deferred.onRejected if (typeof cb !== 'function') { (me._state ? deferred.resolve : deferred.reject)(me._value); return; } var ret; try { ret = cb(me._value); } catch (e) { deferred.reject(e); return; } deferred.resolve(ret); }) } function resolve(newValue) { try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure if (newValue === this) throw new TypeError(); if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { var then = newValue.then; if (typeof then === 'function') { doResolve(then.bind(newValue), resolve.bind(this), reject.bind(this)); return; } } this._state = true; this._value = newValue; finale.call(this); } catch (e) { reject.call(this, e); } } function reject(newValue) { this._state = false; this._value = newValue; finale.call(this); } function finale() { for (var i = 0, len = this._deferreds.length; i < len; i++) { handle.call(this, this._deferreds[i]); } this._deferreds = null; } /** * Take a potentially misbehaving resolver function and make sure * onFulfilled and onRejected are only called once. * * Makes no guarantees about asynchrony. */ function doResolve(fn, onFulfilled, onRejected) { var done = false; try { fn(function (value) { if (done) return; done = true; onFulfilled(value); }, function (reason) { if (done) return; done = true; onRejected(reason); }) } catch (ex) { if (done) return; done = true; onRejected(ex); } } Promise.prototype['catch'] = function (onRejected) { return this.then(null, onRejected); }; Promise.prototype.then = function(onFulfilled, onRejected) { var me = this; return new Promise(function(resolve, reject) { handle.call(me, { onFulfilled: onFulfilled, onRejected: onRejected, resolve: resolve, reject: reject }); }) }; Promise.resolve = function (value) { if (value && typeof value === 'object' && value.constructor === Promise) { return value; } return new Promise(function (resolve) { resolve(value); }); }; Promise.reject = function (value) { return new Promise(function (resolve, reject) { reject(value); }); }; return Promise; } if (typeof module !== 'undefined') { module.exports = MakePromise; }