Promise 是异步编程的一种解决方案,比传统的回调函数或事件更正当和更灵便。本文次要展现 Promise 提供的办法列表,以及根本的实现原理。通过本文,咱们能加深 Promise 办法的了解和场景应用,对 Promise.all、Promise.race、Promise.allSettled 和 Promise.any 四个办法的异同之处也有更深层次的领悟。一、Promise 办法列表Promise 的实例办法有 then/catch/finally 三种,静态方法有 all/race/allSettled/any/resolve/reject 六种。其中 then 实现起来因为波及 Promise 裁决过程(The Promise Resolution Procedure),会比较复杂,其余的都是基于已有性能的拓展。上面都给大伙列出所有的办法。Promise.prototype.then()Promise.prototype.catch()Promise.prototype.finally()Promise.all()Promise.race)Promise.allSettled)Promise.any()Promise.resolve()Promise.reject()二、Promise 九种办法实现1. 原型办法 thenthen 办法是整个 Promise 解决的核心内容,同时因为回调函数和返回一个新的 Promise 实例,因而决定过程比较复杂。// class MyPromise {// static PENDING = 'pending'; // 进行中// static FULFILLED = 'fulfilled'; // 已胜利// static REJECTED = 'rejected'; // 已失败// state = MyPromise.PENDING;// value = null;// reason = null;// onFulfilledCallbacks = [];// onRejectedCallbacks = [];// ...// }MyPromise.prototype.then = (onFulfilled, onRejected) => { if (typeof onFulfilled != 'function') { onFulfilled = (value) => value; } if (typeof onRejected != 'function') { onRejected = (reason) => { throw reason; }; } // Promise 外围解决过程 见标准2.3 const _resolvePromise = (promise, x, resolve, reject) => { // 2.3.1 如果 promise 和 x 指向同一对象,抛出 TypeError 谬误 if (promise === x) { const errMsg = 'The promise and the return value are the same'; return reject(new TypeError(errMsg)); } // 2.3.3 如果 x 为对象(不是null)或者函数 if ((typeof x === 'object' && x !== null) || typeof x === 'function') { let then = null; try { // 2.3.3.1. 检索属性 x.then then = x.then; } catch (error) { // 2.3.3.2 如果 x.then 导致抛出异样 e,则以 e 为回绝起因回绝 promis return reject(error); } // 2.3.3.3 如果 then 是一个函数,x 作为 then 的 this 调用该办法,第一个参数是胜利的回调函数,第二个参数是失败的回调函数 if (typeof then === 'function') { let called = false; try { then.call( x, (y) => { // 2.3.3.3.4 如果胜利回调与失败回调都被调用或屡次调用同一个参数,则第一个调用优先,其余调用都将被疏忽。 if (called) return; called = true; // 2.3.3.3.1 如果胜利回调以值 y 调用,运行 [[Resolve]](promise,y) _resolvePromise(promise, y, resolve, reject); }, (r) => { // 2.3.3.3.4 如果胜利回调与失败回调都被调用或屡次调用同一个参数,则第一个调用优先,其余调用都将被疏忽。 if (called) return; called = true; // 2.3.3.3.2 如果失败回调以起因 r 调用,用 r 回绝 promise reject(r); } ); } catch (error) { // 2.3.3.4 如果调用 then 办法抛出异样 e: // 2.3.3.4.1 若胜利回调或失败回调都调用过,疏忽 if (called) return; // 2.3.3.4.2 未调用,用 e 作为起因回绝 promise reject(error); } } else { // 2.3.3.4. 如果 then 不是函数,用 x 作为值实现 promise return resolve(x); } } else { // 2.3.4 如果 x 不为对象或者函数,以 x 为参数执行 promise return resolve(x); } }; // 链式返回的Promise const newPromise = new MyPromise((resolve, reject) => { switch (this.state) { case MyPromise.FULFILLED: setTimeout(() => { try { const x = onFulfilled(this.value); _resolvePromise(newPromise, x, resolve, reject); } catch (reason) { reject(reason); } }, 0); break; case MyPromise.REJECTED: setTimeout(() => { try { const x = onRejected(this.reason); _resolvePromise(newPromise, x, resolve, reject); } catch (reason) { reject(reason); } }, 0); break; case MyPromise.PENDING: this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled(this.value); _resolvePromise(newPromise, x, resolve, reject); } catch (reason) { reject(reason); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected(this.reason); _resolvePromise(newPromise, x, resolve, reject); } catch (reason) { reject(reason); } }, 0); }); break; } }); return newPromise;};2. 原型办法 catch如果下面没有定义 reject 办法或者在抛出谬误,那么所有的异样会走向 catch 办法,而 catch 能够复用 then 办法。MyPromise.prototype.catch = function (onRejected) { return this.then(null, onRejected);};3. 原型办法 finally不论是 resolve 还是 reject 都会调用 finally 。那么相当于 fianlly 办法替使用者别离调用了一次 then 的 resolved 和 rejected 状态回调。MyPromise.prototype.finally = function (fn) { return this.then( (value) => { fn(); return value; }, (reason) => { fn(); throw reason; } );};4. 静态方法 Promise.allPromise.all() 办法用于将多个 Promise 实例,包装成一个新的 Promise 实例。所有参数数组 Promise 实例执行 resolve 回调后,新实例执行 resolve 回调;如果两头有任何一个 Promise 实例执行 reject 回调,那么新实例就间接执行 reject 回调了。打个比方:多名员工别离同时进行多个我的项目,你要求任何一个我的项目都必须是令你称心的,有一个不称心都算这件事(所有我的项目)是失败的。强调的是整体令你称心。MyPromise.all = function (promises) { return new Promise((resolve, reject) => { if (promises.length === 0) { resolve([]); } else { let result = []; let index = 0; for (let i = 0; i < promises.length; i++) { promises[i].then( (data) => { result[i] = data; if (++index === promises.length) { resolve(result); } }, (err) => { reject(err); return; } ); } } });};5. 静态方法 Promise.racePromise.race() 顾名思义,就是比赛,返回最快实现那一个 Promise 实例。只有参数数组中有一个 Promise 实例执行 resolve 回调或 reject 回调后,新实例就间接返回后果。打个比方:多名员工别离同时进行多个我的项目,你只有最快实现的我的项目,无论我的项目是否令你称心。强调的是要快。MyPromise.race = function (promises) { return new Promise((resolve, reject) => { if (promises.length === 0) { resolve(); } else { let index = 0; for (let i = 0; i < promises.length; i++) { promises[i].then( (data) => { resolve(data); }, (err) => { reject(err); return; } ); } } });};6. 静态方法 Promise.allSettledPromise.allSettled() 办法只有等到参数数组的所有 Promise 实例都产生状态变更,返回的 Promise 实例才会产生状态变更,无论是执行 resolve 回调还是 reject 回调的状态。打个比方:多名员工别离同时进行多个我的项目,你要求每个一个我的项目都必须实现,而后失去所有我的项目是令你称心还是令你不称心的。强调的是最终后果。MyPromise.allSettled = function (promises) { return new Promise((resolve, reject) => { if (promises.length === 0) { resolve([]); } else { let result = []; let index = 0; for (let i = 0; i < promises.length; i++) { promises[i] .then( (value) => { result[i] = { status: 'fulfilled', value, }; }, (reason) => { result[i] = { status: 'rejected', reason, }; } ) .finally(() => { if (++index === promises.length) { return resolve(result); } }); } } });};同时因为 Promise.allSettled() 和 Promise.all() 都是对所有 Promise 实例的一种解决,上面就能够利用 Promise.all() 来实现 Promise.allSettled() 办法。MyPromise.allSettled = function (promises) { return Promise.all( promises.map((item) => Promise.resolve(item).then( (value) => ({ status: 'fulfilled', value }), (reason) => ({ status: 'rejected', reason }) ) ) );};7. 静态方法 Promise.anyPromise.any() 办法是返回任意一个最快执行 resolve 回调的 Promise 实例。打个比方:多名员工同时进行多个我的项目,你只有最快失去令你称心的那个我的项目,无论所有我的项目最终都没令你称心,这件事(所有我的项目)才算是失败了。强调的是又快又好。MyPromise.any = function (promises) { return new Promise((resolve, reject) => { if (promises.length === 0) { return resolve(); } else { let result = []; let index = 0; for (let i = 0; i < promises.length; i++) { promises[i].then( (value) => { return resolve(value); }, (reason) => { result[i] = reason; if (++index === promises.length) { return reject(new AggregateError(result)); } } ); } } });};8. 静态方法 Promise.resolvePromise.resolve 办法返回一个以给定值解析后的 Promise 实例。相当于执行 then 办法外面的 _resolvePromise。MyPromise.reject = function (value) { return new MyPromise((resolve, reject) => { resolve(value); });};9. 静态方法 Promise.rejectPromise.reject 办法返回一个带有回绝起因的 Promise 实例。MyPromise.reject = function (reason) { return new MyPromise((resolve, reject) => { reject(reason); });};