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);  });};