一文简单看懂Promise实现原理

Promise 的实现原理基于 状态机 模型,通过管理异步操作的状态来保证代码的正确执行顺序。具体来说,Promise 的实现涉及以下几个关键点:

1. Promise 的三种状态

  • Pending:初始状态,表示操作尚未完成。
  • Fulfilled:表示操作成功完成,且有结果。
  • Rejected:表示操作失败,并且有错误信息。

一个 Promise 在生命周期中只能从 Pending 状态转到 FulfilledRejected,一旦转到这两种状态,它就不会再变化了。

2. Promise 的构造函数

Promise 的构造函数接收一个 executor(执行器)函数,这个函数会立即执行,并接收两个参数:resolvereject。这两个函数用来改变 Promise 的状态,resolve 用来将状态从 Pending 变为 Fulfilledreject 用来将状态变为 Rejected

ini 复制代码
javascript
复制代码
function MyPromise(executor) {
  this.state = "pending"; // 初始状态为 pending
  this.value = undefined;  // 保存成功的结果
  this.reason = undefined; // 保存失败的原因
  this.onFulfilled = []; // 存储 then 的成功回调
  this.onRejected = [];  // 存储 then 的失败回调

  const resolve = (value) => {
    if (this.state === "pending") {
      this.state = "fulfilled";
      this.value = value;
      this.onFulfilled.forEach(callback => callback(value)); // 调用所有成功回调
    }
  };

  const reject = (reason) => {
    if (this.state === "pending") {
      this.state = "rejected";
      this.reason = reason;
      this.onRejected.forEach(callback => callback(reason)); // 调用所有失败回调
    }
  };

  executor(resolve, reject); // 执行执行器函数
}

3. then 方法的实现

then 方法用于处理 Promise 的结果,接收两个参数:一个成功回调(onFulfilled)和一个失败回调(onRejected)。它返回一个新的 Promise,因此可以进行链式调用。

  • 当 Promise 的状态变为 Fulfilled 时,执行 onFulfilled 回调。
  • 当 Promise 的状态变为 Rejected 时,执行 onRejected 回调。
ini 复制代码
javascript
复制代码
MyPromise.prototype.then = function(onFulfilled, onRejected) {
  const self = this;
  return new MyPromise((resolve, reject) => {
    if (self.state === "fulfilled") {
      // 如果当前 Promise 已经完成,直接调用 onFulfilled
      onFulfilled(self.value);
    } else if (self.state === "rejected") {
      // 如果当前 Promise 已经失败,直接调用 onRejected
      onRejected(self.reason);
    } else {
      // 如果还在 pending 状态,存储回调函数
      self.onFulfilled.push(onFulfilled);
      self.onRejected.push(onRejected);
    }
  });
};

4. 链式调用与回调函数的执行

每次调用 then 方法时,都会返回一个新的 Promise,因此可以实现链式调用。此时,then 方法的回调执行时可能会改变 Promise 的状态,这些变化会通过新的 Promise 继续传递下去。

5. 状态不可变性

一旦 Promise 的状态从 Pending 转变为 FulfilledRejected ,它的状态就不可更改,且所有的回调(onFulfilledonRejected)会按顺序执行。如果某个回调函数返回了一个新的 Promise,新的 Promise 会根据返回值的状态决定是执行成功的回调还是失败的回调。

javascript 复制代码
javascript
复制代码
// 示例
const promise = new MyPromise((resolve, reject) => {
  resolve("成功!");
});

promise.then(result => {
  console.log(result); // 输出 "成功!"
  return "继续成功";
}).then(result => {
  console.log(result); // 输出 "继续成功"
});

6. 总结原理

  • Promise 基于 状态机 模式,管理异步操作的状态。
  • 状态变更:从 PendingFulfilledRejected,且不可逆。
  • resolvereject 用于改变 Promise 的状态。
  • then 方法用于处理成功或失败的回调函数,并且可以返回一个新的 Promise 以支持链式调用。
相关推荐
GreenTea19 分钟前
GrokBot 核心成员 Lauren Tan:每月交付 2000 个 PR 的人,是怎么用 AI 的
前端·后端·架构
mCell2 小时前
用 Knip 清理 AI Coding 留下的冗余代码
前端·ai编程·前端工程化
笃行3502 小时前
使用Rokid AIUI做了一个童年推箱子游戏
前端
excel3 小时前
前端加密的作用与使用场景
前端
计算机魔术师4 小时前
纽约时报版权诉讼披露:微软高管内部称训练 AI 是人类历史上最大规模劳动窃取
前端
去伪存真5 小时前
大模型的参数量为什么那么大?
前端·人工智能
IT_陈寒5 小时前
Java空指针这次真把我坑惨了
前端·人工智能·后端
高级程序源6 小时前
django大学生创新创业项目管理系统94923-计算机课程设计、毕业设计
javascript·vue.js·spring boot·后端·python·django·课程设计
Sam_Deep_Thinking6 小时前
new Thread()之后发生了什么?
java·后端·面试·程序员
八荒启·交互动画6 小时前
# Web特效020—让 Web 特效真正动起来:时间循环应该怎么接
前端·webgl·网页特效·八荒启-交互动画·八荒启