一文简单看懂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 以支持链式调用。
相关推荐
quweiie34 分钟前
tp8.0\jwt接口安全验证
前端·安全·jwt·thinkphp
xiaoyan20151 小时前
最新Flutter3.32+Dart3仿微信App聊天实例
前端·flutter·dart
汪敏wangmin1 小时前
Fiddler-抓包后直接生成Loadrunner脚本或者Jmeter脚本
前端·jmeter·fiddler
没有bug.的程序员2 小时前
JAVA面试宝典 -《安全攻防:从 SQL 注入到 JWT 鉴权》
java·安全·面试
彤银浦2 小时前
Web学习笔记3
前端·笔记·学习·html5
江城开朗的豌豆2 小时前
退出登录后头像还在?这个缓存问题坑过多少前端!
前端·javascript·vue.js
江城开朗的豌豆2 小时前
Vue的'读心术':它怎么知道数据偷偷变了?
前端·javascript·vue.js
江城开朗的豌豆2 小时前
手把手教你造一个自己的v-model:原来双向绑定这么简单!
前端·javascript·vue.js
我在北京coding2 小时前
el-tree 懒加载 loadNode
前端·vue.js·elementui
江城开朗的豌豆2 小时前
v-for中key值的作用:为什么我总被要求加这个'没用的'属性?
前端·javascript·vue.js