/** * Promise对象的内部状态 * * @type {Object} */ var Status = { PENDING: 'pending', FULLFILLED: 'resolved', REJECTED: 'rejected' }; function empty() {} /** * Promise构造函数 * * @constructor * @param {Function} resolver 此Promise对象管理的任务 */ function Promise(resolver) { // ES6原生的Promise构造函数中,若不通过`new`调用Promise的构造函数,会抛出TypeError异常。此处与其一致 if (!(this instanceof Promise)) { throw new TypeError('TypeError: undefined is not a promise'); } // ES6原生的Promise构造函数中,若无作为函数的resolver参数,会抛出TypeError异常。此处与其一致 if (typeof resolver !== 'function') { throw new TypeError('TypeError: Promise resolver undefined is not a function'); } /** * Promise对象内部的状态,初始为`pending`。状态只能由`pending`到`fullfilled`或`rejected` * * @type {string} */ this._status = Status.PENDING; /** * Promise对象resolved/rejected后拥有的data/reason * * - 此处保存此值是为了当一个Promise对象被resolved或rejected后,继续对其调用`then`添加任务,后续处理仍能获得当前Promise的值 * * @type {Mixed} */ this._value; /** * 当前Promise被resolved/rejected后,需处理的任务 * * - 由于同一个Promise对象可以调用多次`then`方法,以添加多个并行任务,所以此处是一个数组 * * @type {Array.} */ this._doneCallbacks = []; this._failCallbacks = []; var promise = this; resolver( function (data) { resolve(promise, data); }, function (reason) { reject(promise, reason); } ); } Promise.prototype = { constructor: Promise, /** * Promise的`then`方法 * * @param {Function|Mixed} onResolve 当前Promise对象被resolved后,需处理的任务 * @param {Function|Mixed} onReject 当前Promise对象被rejected后,需处理的任务 * @return {Promise} 返回一个新的Promise对象,用于链式操作 */ then: function (onResolve, onReject) { var promise = new Promise(empty); this._doneCallbacks.push(makeCallback(promise, onResolve, 'resolve')); this._failCallbacks.push(makeCallback(promise, onReject, 'reject')); // 如果在一个已经被fullfilled或rejected的promise上调用then,则需要直接执行通过then注册的回调函数 run(this); return promise; }, /** * Promise的`done`方法 * * @param {Function|Mixed} onResolve 当前Promise对象被resolved后,需处理的任务 * @return {Promise} 返回一个新的Promise对象,用于链式操作 */ done: function (onResolve) { return this.then(onResolve, null); }, /** * Promise的`fail`方法 * * @param {Function|Mixed} onReject 当前Promise对象被rejected后,需处理的任务 * @return {Promise} 返回一个新的Promise对象,用于链式操作 */ fail: function (onReject) { return this.then(null, onReject); }, /** * Promise的`catch`方法 * * @param {Function|Mixed} onFail 当前Promise对象被rejected后,需处理的任务 * @return {Promise} 返回一个新的Promise对象,用于链式操作 */ catch: function (onFail) { return this.then(null, onFail); } }; /** * 创建一个Promise对象,并用给定值resolve它 * * @param {Mixed} value 用于resolve新创建的Promise对象的值 * @return {Promise} 返回一个新的Promise对象,用于链式操作 */ Promise.resolve = function (value) { var promise = new Promise(empty); resolve(promise, value); return promise; }; /** * 创建一个Promise对象,并用给定值reject它 * * @param {Mixed} reason 用于reject新创建的Promise对象的值 * @return {Promise} 返回一个新的Promise对象,用于链式操作 */ Promise.reject = function (reason) { var promise = new Promise(empty); reject(promise, reason); return promise; }; /** * 返回一个promise,这个promise在iterable中的任意一个promise被解决或拒绝后, * 立刻以相同的解决值被解决或以相同的拒绝原因被拒绝 * * @param {Iterable.} iterable 一组Promise对象或其它值 * @return {Promise} 返回一个新的Promise对象,用于链式操作 */ Promise.race = function (iterable) { if (!iterable || !iterable.hasOwnProperty('length')) { throw new TypeError('TypeError: Parameter `iterable` must be a iterable object'); } var promise = new Promise(empty); for (var i = 0, len = iterable.length; i < len; i++) { var iterate = iterable[i]; if (!(iterate instanceof Promise)) { iterate = Promise.resolve(iterate); } iterate.then(resolveRaceCallback, rejectRaceCallback); } var settled = false; function resolveRaceCallback(data) { if (settled) { return; } settled = true; resolve(promise, data); } function rejectRaceCallback(reason) { if (settled) { return; } settled = true; reject(promise, reason); } }; /** * 返回一个promise,该promise会在iterable参数内的所有promise都被解决后被解决 * * @param {Iterable.} iterable 一组Promise对象或其它值 * @return {Promise} 返回一个新的Promise对象,用于链式操作 */ Promise.all = function (iterable) { if (!iterable || !iterable.hasOwnProperty('length')) { throw new TypeError('TypeError: Parameter `iterable` must be a iterable object'); } var promise = new Promise(empty); var length = iterable.length; for (var i = 0; i < length; i++) { var iterate = iterable[i]; if (!(iterate instanceof Promise)) { iterate = Promise.resolve(iterate); } iterate.then(makeAllCallback(iterate, i, 'resolve'), makeAllCallback(iterate, i, 'reject')); } var result = []; var count = 0; function makeAllCallback(iterate, index, action) { return function (value) { if (action === 'reject') { reject(promise, value); return; } result[index] = value; if (++count === length) { resolve(promise, result); } } } }; /** * 返回一个Deferred对象,包含一个新创建的Promise对象,以及`resolve`和`reject`方法 * * @return {Deferred} */ Promise.defer = function () { var promise = new Promise(empty); return { promise: promise, resolve: function (data) { resolve(promise, data); }, reject: function (reason) { reject(promise, reason); } }; }; function run(promise) { // `then`方法中也会调用,所以此处仍需做一次判断 if (promise._status === Status.PENDING) { return; } var value = promise._value; var callbacks = promise._status === Status.FULLFILLED ? promise._doneCallbacks : promise._failCallbacks; // Promise需要异步操作 setTimeout(function () { for (var i = 0, len = callbacks.length; i < len; i++) { callbacks[i](value); } }); // 每个promise只能被执行一次。虽然`_doneCallbacks`和`_failCallbacks`用户不应该直接访问, // 但还是可以访问到,保险起见,做清空处理。 promise._doneCallbacks = []; promise._failCallbacks = []; } function resolve(promise, data) { if (promise._status !== Status.PENDING) { return; } promise._status = Status.FULLFILLED; promise._value = data; run(promise); } function reject(promise, reason) { if (promise._status !== Status.PENDING) { return; } promise._status = Status.REJECTED; promise._value = reason; run(promise); } function makeCallback(promise, callback, action) { return function promiseCallback(value) { // 如果传递了callback,则使用前一个promise传递过来的值作为参数调用callback, // 并根据callback的调用结果来处理当前promise if (typeof callback === 'function') { var x; try { x = callback(value); } catch (e) { // 如果调用callback时抛出异常,则直接用此异常对象reject当前promise reject(promise, e); } // 如果callback的返回值是当前promise,为避免造成死循环,需要抛出异常 // 根据Promise+规范,此处应抛出TypeError异常 if (x === promise) { var reason = new TypeError('TypeError: The return value could not be same with the promise'); reject(promise, reason); } // 如果返回值是一个Promise对象,则当返回的Promise对象被resolve/reject后,再resolve/reject当前Promise else if (x instanceof Promise) { x.then( function (data) { resolve(promise, data); }, function (reason) { reject(promise, reason); } ); } else { var then; (function resolveThenable(x) { // 如果返回的是一个Thenable对象(此处逻辑有点坑,参照Promise+的规范实现) if (x && (typeof x === 'object'|| typeof x === 'function')) { try { then = x.then; } catch (e) { reject(promise, e); return; } if (typeof then === 'function') { // 调用Thenable对象的`then`方法时,传递进去的`resolvePromise`和`rejectPromise`方法(及下面的两个匿名方法) // 可能会被重复调用。但Promise+规范规定这两个方法有且只能有其中的一个被调用一次,多次调用将被忽略。 // 此处通过`invoked`来处理重复调用 var invoked = false; try { then.call( x, function (y) { if (invoked) { return; } invoked = true; // 避免死循环 if (y === x) { throw new TypeError('TypeError: The return value could not be same with the previous thenable object'); } // y仍有可能是thenable对象,递归调用 resolveThenable(y); }, function (e) { if (invoked) { return; } invoked = true; reject(promise, e); } ); } catch (e) { // 如果`resolvePromise`和`rejectPromise`方法被调用后,再抛出异常,则忽略异常 // 否则用异常对象reject此Promise对象 if (!invoked) { reject(promise, e); } } } else { resolve(promise, x); } } else { resolve(promise, x); } }(x)); } } // 如果未传递callback,直接用前一个promise传递过来的值resolve/reject当前Promise对象 else { action === 'resolve' ? resolve(promise, value) : reject(promise, value); } }; } module.exports = Promise