一文简单看懂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 以支持链式调用。
相关推荐
从兄29 分钟前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
鱼跃鹰飞1 小时前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试
清灵xmf2 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨2 小时前
VUE+Vite之环境文件配置及使用环境变量
前端
GDAL2 小时前
npm入门教程1:npm简介
前端·npm·node.js
小白白一枚1113 小时前
css实现div被图片撑开
前端·css
薛一半3 小时前
PC端查看历史消息,鼠标向上滚动加载数据时页面停留在上次查看的位置
前端·javascript·vue.js
@蒙面大虾3 小时前
CSS综合练习——懒羊羊网页设计
前端·css
过期的H2O23 小时前
【H2O2|全栈】JS进阶知识(四)Ajax
开发语言·javascript·ajax
MarcoPage3 小时前
第十九课 Vue组件中的方法
前端·javascript·vue.js