写点什么

5K 字 由浅入深聊聊 Promise 实现原理

作者:梁木由
  • 2023-01-30
    北京
  • 本文字数:13916 字

    阅读完需:约 46 分钟

5K字 由浅入深聊聊Promise实现原理

前言

大家好,我是梁木由,是一个有想头的前端。这几天再回顾基础知识时,对Promise有了较为深入的理解,那今天就来分享下怎么由浅入深的掌握Promise并且学会手写Promise

概念

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。


所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise 拉出来单练

那我们先把 Promise 拉出来练练,看看是什么玩意,在控制台中打印看下



在上图可以看出什么信息呢,那我们罗列下


  • 首先我们看出在new Promise时,需要传入一个回调函数

  • 它是一个类,并且会返回一个 Promise 对象

  • 那还可以看出它有constructor构造函数,还有catchfinallythen三个方法


那我们根据上述分析出的信息,简单实现一下


class CustomPromise {  constructor(callBack) {  }  catch() {  }  then() {  }  finally() {  }}const customPromise = new CustomPromise()console.log(customPromis)
复制代码


看下我们自己简单实现的输出结果



那我们再写一个 Promise 的常规用法


const promise = new Promise((resolve, reject) => {  console.log("hellow Promise");});console.log(promise);
复制代码



那我们来看看打印结果,能分析出什么结果


  • hellow promise 在控制台被输出了,那是不是说我们传入的回调函数被立即执行了,那说明传入的是一个执行器


那再改进一下我们的 CustomPromise


class CustomPromise {  constructor(executor) {      executor()  }  catch() { }  then() { }  finally() { }}const customPromise = new CustomPromise((resolve, reject) => {  console.log('hellow Promise')})console.log(customPromise)
复制代码

Promise 基本原理与基本特征

那我们来看看我们所熟知的Promise的基本原理


  • 首先我们在调用 Promise 时,会返回一个 Promise 对象。

  • 构建 Promise 对象时,需要传入一个 executor 函数,Promise 的主要业务流程都在 executor 函数中执行。

  • 如果运行在 excutor 函数中的业务执行成功了,会调用 resolve 函数;如果执行失败了,则调用 reject 函数。

  • Promise 的状态不可逆,同时调用 resolve 函数和 reject 函数,默认会采取第一次调用的结果。


结合 Promise/A+规范,我们还可以分析出哪些基本特征


Promise/A+的规范比较多,在这列出一下核心的规范。Promise/A+规范


  • promise 有三个状态:pending,fulfilled,rejected,默认状态是 pending。

  • promise 有一个 value 保存成功状态的值,有一个 reason 保存失败状态的值,可以是 undefined/thenable/promise。

  • promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled,状态一旦确认,就不会再改变。

  • promise 必须有一个 then 方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, 和 promise 失败的回调 onRejected。

  • 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个 then 的失败的回调 onRejected。


CustomPromise,还实现不了基本原理的 3,4 两条,那我们来根据基本原理与 Promise/A+分析下,还缺少什么


  • promise 有三个状态:pending,fulfilled,rejected。

  • executor 执行器调用 reject 与 resolve 两个方法

  • 还需要有保存成功或失败两个值的变量

  • then 接收两个参数,分别是成功的回调 onFulfilled,失败的回调 onRejected


那再来改进下CustomPromise


// 定义三个常量表示状态const PENDING = 'pending';const FULFILLED = 'fulfilled';const REJECTED = 'rejected';class CustomPromise {  constructor(executor) {    executor(this.resolve, this.reject);  }  // resolve和reject为什么要用箭头函数?  // 如果直接调用的话,普通函数this指向的是window或者undefined  // 用箭头函数就可以让this指向当前实例对象  resolve = (value) => {    this.value = value;  };  reject = (value) => {    this.reason = value;  };  // 成功之后的值  value = undefined;  // 失败之后的值  reason = undefined;  then(onFulfilled,onRejected) {  }  catch() {  }  finally() {}}
复制代码


那我们根据 Promise 基本原理看看它原生 Promise 的效果


new Promise(function (resolve, reject) {  resolve("成功");  reject("失败");}).then(  (value) => {    console.log(value); // 结果为‘成功’  },  (err) => {    console.log(err);  });new Promise(function (resolve, reject) {  reject("失败");  resolve("成功");}).then(  (value) => {    console.log(value);  },  (err) => {    console.log(err); // 结果为‘失败’  });
复制代码


可以看出与基本原理一样的效果,那我们分析下如何实现这种效果


  • 需要控制 promise 状态

  • 在 then 方法里要调用成功或失败的回调函数


const PENDING = "pending";const FULFILLED = "fulfilled";const REJECTED = "rejected";class CustomPromise {  constructor(executor) {    executor(this.resolve, this.reject);  }  // resolve和reject为什么要用箭头函数?  // 如果直接调用的话,普通函数this指向的是window或者undefined  // 用箭头函数就可以让this指向当前实例对象  resolve = (value) => {    // promise只能从pending到rejected, 或者从pending到fulfilled    if (this.status == PENDING) {      this.status = FULFILLED;      this.value = value;    }  };  reject = (err) => {    // promise只能从pending到rejected, 或者从pending到fulfilled    if (this.status == PENDING) {      this.status = REJECTED;      this.reason = err;    }  };  status = PENDING;  // 成功之后的值  value = undefined;  // 失败之后的值  reason = undefined;  then(onFulfilled, onRejected) {    // 需要判断状态,根据状态选择处理回调函数    if (this.status == FULFILLED) {      onFulfilled(this.value);    } else if (this.status == REJECTED) {      onRejected(this.reason);    }  }  catch() {  }  finally() {}}
复制代码


来测试下CustomPromise


new CustomPromise(function (resolve, reject) {  resolve("成功");  reject("失败");}).then(  (value) => {    console.log(value);// 结果为‘成功’  },  (err) => {    console.log(err);  });new CustomPromise(function (resolve, reject) {  reject("失败");  resolve("成功");}).then(  (value) => {    console.log(value);  },  (err) => {    console.log(err);// 结果为‘失败’  });
复制代码

Promise.then 链式调用

我们都知到 Primose.then 是可以链式调用的,那我们先看看原生效果


const promise = new Promise((resolve, reject) => {  resolve("start");});promise  .then((res) => {    console.log(res);    return new Promise((resolve, reject) => {     setTimeout(() => {        resolve("hellow");     },3000)    });  })  .then((res) => {    console.log(res);    return "promise";  })  .then((res) => {    console.log(res);  });
复制代码


输出结果


starthellowpromise
复制代码


那我们来分析实现一下


  • 首先.then 是需要返回一个 Promise

  • 下一个.then 需要拿到上一个.then 的返回值

  • 有异步操作的话,后一个回调函数,会等待该Promise对象的状态发生变化,在被调用

  • 有异步操作的话,那就是说有任务队列,需要有收集回调函数的队列


const PENDING = "pending";const FULFILLED = "fulfilled";const REJECTED = "rejected";class CustomPromise {  constructor(executor) {    executor(this.resolve, this.reject);  }  // resolve和reject为什么要用箭头函数?  // 如果直接调用的话,普通函数this指向的是window或者undefined  // 用箭头函数就可以让this指向当前实例对象  resolve = (value) => {    // promise只能从pending到rejected, 或者从pending到fulfilled    if (this.status == PENDING) {      this.status = FULFILLED;      this.value = value;      // resolve里面将所有成功的回调拿出来执行      if (this.onResolvedCallbacks.length) {        this.onResolvedCallbacks.forEach((fn) => fn());      }    }  };  reject = (err) => {    // promise只能从pending到rejected, 或者从pending到fulfilled    if (this.status == PENDING) {      this.status = REJECTED;      this.reason = err;      // reject里面将所有失败的回调拿出来执行      if (this.onFulfilledCallbacks.length) {        this.onFulfilledCallbacks.forEach((fn) => fn());      }    }  };  // 存储成功回调函数  onResolvedCallbacks = [];  // 存储失败回调函数  onFulfilledCallbacks = [];  status = PENDING;  // 成功之后的值  value = undefined;  // 失败之后的值  reason = undefined;  then(onFulfilled, onRejected) {    // 如果不传,就使用默认函数,确保是函数类型    onFulfilled =      typeof onFulfilled === "function" ? onFulfilled : (value) => value;    onRejected =      typeof onRejected === "function"        ? onRejected        : (reason) => {            throw reason;          };    const thenCustomPromise = new CustomPromise((resolve, reject) => {      const resolveCustomPromise = (callBack, value) => {        try {          const x = callBack(value);          // 如果相等了,说明return的是自己,抛出类型错误并返回          if (resolveCustomPromise === x) {            return reject(new TypeError("类型错误"));          }          // 判断x是不是 CustomPromise 实例对象          if (x instanceof CustomPromise) {            // 执行 x,调用 then 方法,目的是将其状态变为 fulfilled 或者 rejected            // x.then(value => resolve(value), error => reject(reason))            // 简化之后            x.then(resolve, reject);          } else {            // 普通值            resolve(x);          }        } catch (error) {          reject(error);        }      };      // 需要判断状态,根据状态选择处理回调函数      if (this.status == FULFILLED) {        resolveCustomPromise(onFulfilled, this.value);      } else if (this.status == REJECTED) {        resolveCustomPromise(onRejected, this.reason);      } else if (this.status == PENDING) {        // 当状态为pending时,把then回调push进resolve/reject执行队列,等待执行        this.onResolvedCallbacks.push(() =>          resolveCustomPromise(onFulfilled, this.value)        );        this.onFulfilledCallbacks.push(() =>          resolveCustomPromise(onRejected, this.reason)        );      }    });    return thenCustomPromise;  }  catch() {}  finally() {}}
复制代码


来验证下.then 的链式调用


const promise = new CustomPromise((resolve, reject) => {  resolve("start");});promise  .then((res) => {    console.log(res);    return new CustomPromise((resolve, reject) => {      setTimeout(() => {        resolve("hellow");      }, 1000);    });  })  .then((res) => {    console.log(res);    return "promise";  })  .then((res) => {    console.log(res);  });// 输出结果 start->hellow->promise
复制代码

Promise.prototype.catch()

是 .then(null, rejection) 或是 .then(undefined, rejection)的别名,用于指定发生错误时的回调函数


看下原生 promise 效果


const promise = new Promise((resolve, reject) => {  resolve("start");});promise  .then((res) => {    console.log(res);    return new Promise((resolve, reject) => {      reject("hellow");    });  })  .catch(err => {console.log(err); return 'promise'})  .then(res => console.log(res))
复制代码


输出结果


starthellowpromise
复制代码


根据上述原生 catch 我们来分析下结果


  • 执行.then 的 onRejected 回调函数

  • 并且可以继续链式调用


catch(onFulfilled) {   return this.then(null, onFulfilled)}
复制代码


那我们来验证下


const promise = new CustomPromise((resolve, reject) => {  resolve("start");});promise  .then((res) => {    console.log(res);    return new CustomPromise((resolve, reject) => {      reject("hellow");    });  })  .catch((err) => {    console.log(err);    return "promise";  })  .then((res) => console.log(res));// 输出结果starthellowpromise
复制代码

Promise.resolve()

Promise.resolve(value)返回一个解析过的 Promise 对象,用法有一个 value 参数


  • 如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。



- 如果参数是 具有`then`方法的对象`Promise.resolve()`方法会将这个对象转为 Promise 对象,然后就立即执行`thenable`对象的`then()`方法
- ```javascript let thenable = { then: function(resolve, reject) { resolve('promise'); } }; let p1 = Promise.resolve(thenable); p1.then(function (res) { console.log(res); // promise });
复制代码


  • 如果参数是一个原始值,或者是一个不具有then()方法的对象,则Promise.resolve()方法返回一个新的 Promise 对象,状态为resolved



- `Promise.resolve()`方法允许调用时不带参数,直接返回一个`resolved`状态的 Promise 对象
- ```javascript const p = Promise.resolve(); p.then(function () { // ... });
复制代码


参考资料:[ECMAScript 入门](https://es6.ruanyifeng.com/#docs/promise#Promise-resolve


CustomPromise添加静态 resolve 方法


//静态的resolve方法  static resolve(value) {    if (value instanceof CustomPromise) return value;    return new CustomPromise((resolve) => resolve(value));  }
复制代码

Promise.reject()

Promise.reject(reason) 返回一个 Promise 实例,并且携带 reason


const promise = Promise.reject("rejected message")// 相当于// const promise2 = new Promsie((resolve, reject) => {//   reject("rejected message")// })
复制代码


根据上述例子我们来分析下结果


  • 可以看出无论 reason 传入什么内容,都是经过 reject()方法,那是不是可以理解为就是捕获错误信息


CustomPromise添加静态 reject 方法


//静态的reject方法static reject(reason) {   return new CustomPromise((resolve, reject) => reject(reason));}
复制代码

Promise.prototype.finally()

finally()不接收参数,并且在.then 或.catch 回调函数执行完以后,再执行 finally 中的方法


看下原生 promise 效果


const promise = new Promise((resolve, reject) => {  resolve("start");});promise  .then((res) => {    console.log(res);    return new Promise((resolve, reject) => {      resolve("hellow");    });  })  .then((res) => {    console.log(res);    return new Promise((resolve, reject) => {      resolve("promise");    });  })  .finally(() => {    console.log("finally");    return "is finally";  })  .then((res) => console.log(res));
复制代码


输出结果


starthellowfinallypromise
复制代码


根据上述原生 finally 我们来分析下结果


  • finally 方法和 then 以及 catch 一样,都可以返回一个新的 Promise

  • finally 并不会影响之前返回的 Promise 对象

  • 可以继续链式调用并且获取之前 Promise 的值


CustomPromise添加静态 finally 方法


finally(callback) {    return this.then(      (value) => CustomPromise.resolve(callback()).then(() => value),      (reason) => CustomPromise.resolve(callback()).then(() => reason)    );}
复制代码


那我们来验证下


const promise = new CustomPromise((resolve, reject) => {  resolve("start");});promise  .then((res) => {    console.log(res);    return new CustomPromise((resolve, reject) => {      resolve("hellow");    });  })  .then((res) => {    console.log(res);    return new CustomPromise((resolve, reject) => {      resolve("promise");    });  })  .finally(() => {    console.log("finally");    return "is finally";  })  .then((res) => console.log(res));// 输出结果starthellowfinallypromise
复制代码

Promise.all()

Promise.all() 方法接收一个 promise 的 iterable 类型(Array,Map,Set 都属于 ES6 的 iterable 类型)并返回一个新的 Promise 实例


看下原生Promise.all()效果


let p1 = new Promise((resolve, reject) => {  resolve("start");}).then((res) => res);let p2 = new Promise((resolve, reject) => {  resolve("hellow");}).then((res) => res);let p3 = new Promise((resolve, reject) => {  resolve("promise");}).then((res) => res);Promise.all([p1, p2, p3])  .then((res) => console.log("success:", res))  .catch((err) => console.log("error:", err));// 输出结果 success:['start', 'hellow', 'promise']
复制代码


let p1 = new Promise((resolve, reject) => {  resolve("start");}).then((res) => res);let p2 = new Promise((resolve, reject) => {  reject("报错了");}).then((res) => res);let p3 = new Promise((resolve, reject) => {  reject("报错了2");}).then((res) => res);Promise.all([p1, p2, p3])  .then((res) => console.log("success:", res))  .catch((err) => console.log("error:", err));//输出结果 error:报错了
复制代码


那我们来根据输出结果分析下


  • 成功的时候返回的是一个结果数组

  • 失败的时候则返回最先被 reject 失败状态的值


CustomPromise添加静态 all()方法


  //静态的all方法  static all(values){    let result = [];    let index = 0;    return new CustomPromise((resolve,reject) => {      function addPromise(key, value) {        result[key] = value        index++        if (index === values.length) {          resolve(result)        }      }            for(let i = 0; i < values.length; i++){        let item = values[i];        if(item instanceof CustomPromise){          // 参数为Promise          item.then(value => addPromise(i,value), error => reject(reason))        }else{          // 参数为普通值          addPromise(i,item)        }      }    })  }
复制代码


那我们来验证下


let p1 = new CustomPromise((resolve, reject) => {  resolve("start");});let p2 = new CustomPromise((resolve, reject) => {  resolve("hellow");});let p3 = new CustomPromise((resolve, reject) => {  resolve("promise");});CustomPromise.all([p1, p2, p3])  .then((res) => console.log("success:", res))  .catch((err) => console.log("error:", err));// 输出结果 success:['start', 'hellow', 'promise']
复制代码


let p1 = new CustomPromise((resolve, reject) => {  resolve("start");}).then((res) => res);let p2 = new CustomPromise((resolve, reject) => {  reject("报错了");}).then((res) => res);let p3 = new CustomPromise((resolve, reject) => {  reject("报错了2");}).then((res) => res);CustomPromise.all([p1, p2, p3])  .then((res) => console.log("success:", res))  .catch((err) => console.log("error:", err));//输出结果 error:报错了
复制代码

Promise.race()

Promise.race()方法返回一个 promise,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。


var p1 = new Promise(function(resolve, reject) {    setTimeout(resolve, 300, "start");});var p2 = new Promise(function(resolve, reject) {    setTimeout(resolve, 100, "hellow");});const p = Promise.race([p1, p2]).then(function(value) {  console.log(value); // "hellow"});
复制代码


来分析下那就是有一个实例先改变状态,p 的状态就跟着改变


CustomPromise添加静态 race()方法


//静态race方法  static race(values) {    return new CustomPromise((resolve, reject) => {      for (const p of values) {        p.then(resolve, reject);      }    });  }
复制代码


那我们来验证下


var p1 = new CustomPromise(function(resolve, reject) {    setTimeout(resolve, 300, "start");});var p2 = new CustomPromise(function(resolve, reject) {    setTimeout(resolve, 100, "hellow");});const p = CustomPromise.race([p1, p2]).then(function(value) {  console.log(value); // "hellow"});
复制代码

Promise.allSettled()

Promise.allSettled() 方法不依赖于彼此成功完成的异步任务,不管每一个操作是成功还是失败,再进行下一步操作。


Promise.allSettled([  Promise.resolve('start'),  Promise.reject(new Error("error")),  new Promise((resolve) => setTimeout(() => resolve('hellow'), 0)),  'promise',]).then((values) => console.log(values));// [//   { status: 'fulfilled', value: start },//   { status: 'rejected', reason: Error: error },//   { status: 'fulfilled', value: hellow },//   { status: 'fulfilled', value: promise }// ]
复制代码


来分析下结果


  • status 一个字符串,要么是 "fulfilled",要么是 "rejected",表示 promise 的最终状态。

  • value 当 status"fulfilled",在 promise 解决时才有 value

  • reason 当 status"rejected",在 promsie 拒绝时才有 reason


CustomPromise添加静态 allSettled()方法


//静态allSettled方法  static allSettled(values) {    return new Promise((resolve, reject) => {      let resolveDataList = [],        resolveCount = 0;      const addPromise = (status, value, i) => {        resolveDataList[i] = {          status,          value,        };        resolveCount++;        if (resolveCount === values.length) {          resolve(resolveDataList);        }      };      values.forEach((value, i) => {        if (value instanceof CustomPromise) {          value.then(            (res) => {              addPromise("fulfilled", res, i);            },            (err) => {              addPromise("rejected", err, i);            }          );        } else {          addPromise("fulfilled", value, i);        }      });    });  }
复制代码


来验证下


CustomPromise.allSettled([  CustomPromise.resolve('start'),  CustomPromise.reject(new Error("error")),  new CustomPromise((resolve) => setTimeout(() => resolve('hellow'), 0)),  'promise',]).then((values) => console.log(values));// [//   { status: 'fulfilled', value: start },//   { status: 'rejected', reason: Error: error },//   { status: 'fulfilled', value: hellow },//   { status: 'fulfilled', value: promise }// ]
复制代码

Promise.any()

Promise.any()接收一个由Promise所组成的可迭代对象,返回一个新的promise


const p1 = new Promise((resolve, reject) => {  setTimeout(resolve, 100, "start");});const p2 = new Promise((resolve, reject) => {  reject("报错了");});const p3 = new Promise((resolve, reject) => {  setTimeout(resolve, 500, "promise");});Promise.any([p1, p2, p3]).then((value) => {  console.log(value);  // start})
复制代码


const p1 = new Promise((resolve, reject) => {  setTimeout(reject, 100, "start");});const p2 = new Promise((resolve, reject) => {  reject("报错了");});const p3 = new Promise((resolve, reject) => {  setTimeout(reject, 500, "promise");});Promise.any([p1, p2, p3])  .then((value) => {    console.log("value:", value);  })  .catch((err) => {    console.log("err:", err); //err: AggregateError: All promises were rejected  });
复制代码


那我们来分析下


  • 与 all()不同,只要有一个 promise 成功,会返回首个成功的 promise 的值,方法提前结束

  • 如果所有 Promise 都失败,则报错 All promises were


CustomPromise添加静态 any()方法


//静态any方法  static any(values) {    return new CustomPromise((resolve, reject) => {      let rejectCount = 0;      values.forEach((value) => {        value.then(          (val) => resolve(val),          (err) => {            rejectCount++;            if (rejectCount === value.length) {              reject("All promises were rejected");            }          }        );      });    });  }
复制代码


我们来验证下


const p1 = new CustomPromise((resolve, reject) => {  setTimeout(resolve, 100, "start");});const p2 = new CustomPromise((resolve, reject) => {  reject("报错了");});const p3 = new CustomPromise((resolve, reject) => {  setTimeout(resolve, 500, "promise");});CustomPromise.any([p1, p2, p3])  .then((value) => {    console.log("value:", value); //value: start  })  .catch((err) => {    console.log("err:", err);  });
复制代码


const p1 = new CustomPromise((resolve, reject) => {  setTimeout(reject, 100, "start");});const p2 = new CustomPromise((resolve, reject) => {  reject("报错了");});const p3 = new CustomPromise((resolve, reject) => {  setTimeout(reject, 500, "promise");});CustomPromise.any([p1, p2, p3])  .then((value) => {    console.log("value:", value);  })  .catch((err) => {    console.log("err:", err); //err: All promises were rejected  });
复制代码

完整代码

const PENDING = "pending";const FULFILLED = "fulfilled";const REJECTED = "rejected";class CustomPromise {  constructor(executor) {    try {      executor(this.resolve, this.reject);    } catch (error) {      // 如果有错误,就直接执行 reject      this.reject(error);    }  }  // resolve和reject为什么要用箭头函数?  // 如果直接调用的话,普通函数this指向的是window或者undefined  // 用箭头函数就可以让this指向当前实例对象  resolve = (value) => {    // promise只能从pending到rejected, 或者从pending到fulfilled    if (this.status == PENDING) {      this.status = FULFILLED;      this.value = value;      // resolve里面将所有成功的回调拿出来执行      if (this.onResolvedCallbacks.length) {        this.onResolvedCallbacks.forEach((fn) => fn());      }    }  };  reject = (err) => {    // promise只能从pending到rejected, 或者从pending到fulfilled    if (this.status == PENDING) {      this.status = REJECTED;      this.reason = err;      // reject里面将所有失败的回调拿出来执行      if (this.onFulfilledCallbacks.length) {        this.onFulfilledCallbacks.forEach((fn) => fn());      }    }  };  // 存储成功回调函数  onResolvedCallbacks = [];  // 存储失败回调函数  onFulfilledCallbacks = [];  status = PENDING;  // 成功之后的值  value = undefined;  // 失败之后的值  reason = undefined;  then(onFulfilled, onRejected) {    // 如果不传,就使用默认函数,确保是函数类型    onFulfilled =      typeof onFulfilled === "function" ? onFulfilled : (value) => value;    onRejected =      typeof onRejected === "function"        ? onRejected        : (reason) => {            throw reason;          };    const thenCustomPromise = new CustomPromise((resolve, reject) => {      const resolveCustomPromise = (callBack, value) => {        try {          const x = callBack(value);          // 如果相等了,说明return的是自己,抛出类型错误并返回          if (resolveCustomPromise === x) {            return reject(new TypeError("类型错误"));          }          // 判断x是不是 CustomPromise 实例对象          if (x instanceof CustomPromise) {            // 执行 x,调用 then 方法,目的是将其状态变为 fulfilled 或者 rejected            // x.then(value => resolve(value), error => reject(reason))            // 简化之后            x.then(resolve, reject);          } else {            // 普通值            resolve(x);          }        } catch (error) {          reject(error);        }      };      // 需要判断状态,根据状态选择处理回调函数      if (this.status == FULFILLED) {        resolveCustomPromise(onFulfilled, this.value);      } else if (this.status == REJECTED) {        resolveCustomPromise(onRejected, this.reason);      } else if (this.status == PENDING) {        // 当状态为pending时,把then回调push进resolve/reject执行队列,等待执行        this.onResolvedCallbacks.push(() =>          resolveCustomPromise(onFulfilled, this.value)        );        this.onFulfilledCallbacks.push(() =>          resolveCustomPromise(onRejected, this.reason)        );      }    });    return thenCustomPromise;  }  catch(onFulfilled) {    return this.then(null, onFulfilled);  }  finally(callback) {    return this.then(      (value) => CustomPromise.resolve(callback()).then(() => value),      (reason) => CustomPromise.resolve(callback()).then(() => reason)    );  }  //静态的resolve方法  static resolve(value) {    if (value instanceof CustomPromise) return value;    return new CustomPromise((resolve) => resolve(value));  }  //静态的reject方法  static reject(reason) {    return new CustomPromise((resolve, reject) => reject(reason));  }  //静态的all方法  static all(values) {    // 用来记录Promise成功的次数    let resolveCount = 0,      // 用来保存Promise成功的结果      resolveDataList = [];    return new CustomPromise((resolve, reject) => {      function addPromise(key, value) {        resolveDataList[key] = value;        resolveCount++;        if (resolveCount === values.length) {          resolve(resolveDataList);        }      }      for (let i = 0; i < values.length; i++) {        let item = values[i];        if (item instanceof CustomPromise) {          // 参数为Promise          item.then(            (value) => addPromise(i, value),            (error) => reject(error)          );        } else {          // 参数为普通值          addPromise(i, item);        }      }    });  }  //静态race方法  static race(values) {    return new CustomPromise((resolve, reject) => {      for (const p of values) {        p.then(resolve, reject);      }    });  }  //静态allSettled方法  static allSettled(values) {    return new Promise((resolve, reject) => {      let resolveDataList = [],        resolveCount = 0;      const addPromise = (status, value, i) => {        resolveDataList[i] = {          status,          value,        };        resolveCount++;        if (resolveCount === values.length) {          resolve(resolveDataList);        }      };      values.forEach((value, i) => {        if (value instanceof CustomPromise) {          value.then(            (res) => {              addPromise("fulfilled", res, i);            },            (err) => {              addPromise("rejected", err, i);            }          );        } else {          addPromise("fulfilled", value, i);        }      });    });  }  //静态any方法  static any(values) {    return new CustomPromise((resolve, reject) => {      let rejectCount = 0;      values.forEach((value) => {        value.then(          (val) => resolve(val),          (err) => {            rejectCount++;            if (rejectCount === value.length) {              reject("All promises were rejected");            }          }        );      });    });  }}
复制代码

结语

关于 Promise 的实现就到这里了,希望能跟大家一起进步⛽️⛽️⛽️


如果写的有问题,欢迎大家指出问题,一起讨论,让我再打磨打磨


最后呢,希望大家支持一下长文不易记得给点个赞👍👍👍



发布于: 2023-01-30阅读数: 47
用户头像

梁木由

关注

公众号:前端新气象 2023-01-16 加入

一个有想头的前端,对2023年充满希望、怀抱期待,相信自己做个自律的人。要学习,拒绝躺平,从我做起。⛽️

评论

发布
暂无评论
5K字 由浅入深聊聊Promise实现原理_JavaScript_梁木由_InfoQ写作社区