位置: 文档库 > JavaScript > JS Promise 实现原理 - 手写符合 Promises/A+ 规范的异步解决方案

JS Promise 实现原理 - 手写符合 Promises/A+ 规范的异步解决方案

周奇墨 上传于 2025-07-31 10:48

《JS Promise 实现原理 - 手写符合 Promises/A+ 规范的异步解决方案》

JavaScript 异步编程中,Promise 是核心机制之一。它解决了回调地狱(Callback Hell)问题,提供了链式调用、错误处理等能力。本文将深入解析 Promise 的实现原理,并手写一个符合 Promises/A+ 规范的 Promise 类,帮助读者理解其底层逻辑。

一、Promise 的核心概念

Promise 是一个对象,表示异步操作的最终完成(或失败)及其结果值。它有三种状态:

  • Pending(待定):初始状态,既未完成,也未拒绝。
  • Fulfilled(已兑现):操作成功完成。
  • Rejected(已拒绝):操作失败。

状态一旦改变,就不能再变(从 Pending 到 Fulfilled 或 Rejected)。

二、Promises/A+ 规范要点

Promises/A+ 是 Promise 的通用规范,定义了以下核心行为:

  1. Then 方法:Promise 必须实现 `.then()` 方法,接受两个可选参数(onFulfilled、onRejected)。
  2. 链式调用:`.then()` 返回一个新的 Promise,实现链式调用。
  3. 异步执行:onFulfilled/onRejected 必须异步调用(通过微任务或宏任务)。
  4. 错误传播:若 onFulfilled/onRejected 抛出异常,返回的 Promise 应被拒绝。

三、手写 Promise 实现

以下是一个简化版的 Promise 实现,符合 Promises/A+ 规范:

1. 基础结构

class MyPromise {
  constructor(executor) {
    this.state = 'pending'; // 初始状态
    this.value = undefined; // 成功值
    this.reason = undefined; // 失败原因
    this.onFulfilledCallbacks = []; // 成功回调队列
    this.onRejectedCallbacks = []; // 失败回调队列

    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onFulfilledCallbacks.forEach(fn => fn());
      }
    };

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };

    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }
}

2. 实现 .then() 方法

.then() 需要返回一个新的 Promise,并处理链式调用:

then(onFulfilled, onRejected) {
  // 参数可选处理
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
  onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };

  const promise2 = new MyPromise((resolve, reject) => {
    if (this.state === 'fulfilled') {
      // 模拟异步(通过 setTimeout 模拟微任务)
      setTimeout(() => {
        try {
          const x = onFulfilled(this.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (err) {
          reject(err);
        }
      }, 0);
    } else if (this.state === 'rejected') {
      setTimeout(() => {
        try {
          const x = onRejected(this.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (err) {
          reject(err);
        }
      }, 0);
    } else if (this.state === 'pending') {
      this.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        }, 0);
      });

      this.onRejectedCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        }, 0);
      });
    }
  });

  return promise2;
}

3. resolvePromise 函数

处理 Promise 解析规则(如返回值是 Promise 时的递归解析):

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise'));
  }

  let called = false;
  if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
    try {
      const then = x.then;
      if (typeof then === 'function') {
        then.call(
          x,
          y => {
            if (called) return;
            called = true;
            resolvePromise(promise2, y, resolve, reject);
          },
          r => {
            if (called) return;
            called = true;
            reject(r);
          }
        );
      } else {
        resolve(x);
      }
    } catch (err) {
      if (called) return;
      called = true;
      reject(err);
    }
  } else {
    resolve(x);
  }
}

4. 静态方法:resolve、reject、all、race

// MyPromise.resolve
static resolve(value) {
  if (value instanceof MyPromise) {
    return value;
  }
  return new MyPromise(resolve => resolve(value));
}

// MyPromise.reject
static reject(reason) {
  return new MyPromise((_, reject) => reject(reason));
}

// MyPromise.all
static all(promises) {
  return new MyPromise((resolve, reject) => {
    const results = [];
    let count = 0;
    promises.forEach((promise, index) => {
      MyPromise.resolve(promise).then(
        value => {
          results[index] = value;
          count++;
          if (count === promises.length) resolve(results);
        },
        reject
      );
    });
  });
}

// MyPromise.race
static race(promises) {
  return new MyPromise((resolve, reject) => {
    promises.forEach(promise => {
      MyPromise.resolve(promise).then(resolve, reject);
    });
  });
}

四、测试与验证

使用以下代码验证实现:

const promise = new MyPromise((resolve, reject) => {
  setTimeout(() => resolve('Success!'), 1000);
});

promise
  .then(value => {
    console.log(value); // 输出: Success!
    return 'Next Value';
  })
  .then(value => {
    console.log(value); // 输出: Next Value
  });

五、与原生 Promise 的对比

原生 Promise 的实现更复杂,例如:

  • 使用微任务队列(如 `queueMicrotask` 或 `MutationObserver`)而非 `setTimeout`。
  • 优化了性能和内存占用。
  • 支持更多边缘情况(如 `then` 的多次调用)。

六、关键点总结

  1. 状态不可逆:一旦从 Pending 变为 Fulfilled/Rejected,不能再次改变。
  2. 异步执行:回调必须通过微任务/宏任务延迟执行。
  3. 链式调用:`.then()` 返回新 Promise,实现方法链。
  4. 错误传播:未捕获的异常会传递到下一个 `.then()` 的 `onRejected`。

关键词:JavaScript、Promise、Promises/A+ 规范、异步编程、手写实现状态管理、链式调用、错误处理

简介:本文详细解析了 JavaScript 中 Promise 的核心原理,并手写了一个符合 Promises/A+ 规范的 Promise 类。内容涵盖状态管理、.then() 方法实现、链式调用、异步执行、错误传播等关键点,同时对比了原生 Promise 的实现差异,适合希望深入理解 Promise 机制的开发者。

JavaScript相关