Skip to content

手写 Promise

来源:js/实现/promise.html,手写实现符合 Promises/A+ 规范的 Promise。

速查导航


核心状态

Promise 有三种状态,状态一旦改变就不可逆:

状态含义
pending等待中,可以变为 fulfilled 或 rejected
fulfilled已成功,持有 value
rejected已失败,持有 reason

resolve 与 reject

js

要点:

  • 只有 pending 状态才能修改,保证不可逆
  • onFulfilledCallbacks / onRejectedCallbacks 存储异步回调
  • shift() 逐个取出执行,确保回调按注册顺序触发(shift 不是纯函数,取出后数组失去该元素,直到数组为空)

then 方法

then 需要处理三种情况:

  1. 已 fulfilled → 异步执行成功回调
  2. 已 rejected → 执行失败回调
  3. 仍 pending → 暂存回调,等状态变更时执行
js
then(onFulfilled, onRejected) {
  let promise2 = new MyPromise((resolve, reject) => {
    if (this.status === FULFILLED) {
      queueMicrotask(() => {
        const x = onFulfilled(this.value);
        this.resolvePromise(promise2, x, resolve, reject);
      });
    } else if (this.status === REJECTED) {
      onRejected(this.reason);
    } else if (this.status === PENDING) {
      this.onFulfilledCallbacks.push(onFulfilled);
      this.onRejectedCallbacks.push(onRejected);
    }
  });
  return promise2;
}

queueMicrotask 的作用: 确保 onFulfilled 异步执行,符合 Promises/A+ 规范 2.2.4


resolvePromise

处理 then 回调的返回值,实现链式调用:

js
resolvePromise(promise2, x, resolve, reject) {
  // 如果返回自身,抛 TypeError 防止死循环
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
  }
  // 如果返回的是 Promise,等它决议
  if (x instanceof MyPromise) {
    x.then(resolve, reject);
  } else {
    // 普通值直接 resolve
    resolve(x);
  }
}

完整实现

js

验证要点:

  • 输出顺序:1resolve: success2resolve: successresolve: success
  • 同一个 Promise 可以注册多个 then 回调
  • 异步执行(setTimeout + queueMicrotask)确保回调在微任务队列中触发