1166 字
6 分钟
JavaScript 实现 Promise A+ 规范

题目描述#

实现 Promise A+ 规范

解题思路#

  1. 状态机设计:Promise 必须实现三种状态(pending/fulfilled/rejected)的状态转换机制
  2. 异步处理:then 方法需要支持异步调用,回调需放入微任务队列
  3. 链式调用:then 方法必须返回新 Promise 实现链式调用
  4. 值穿透:当 then 参数不是函数时需要实现值穿透
  5. 错误处理:需要捕获执行器函数和回调函数中的错误
  6. 解决程序:实现复杂的 Promise 解决程序处理 thenable 对象

关键洞察#

  1. 状态不可逆性 Promise 状态只能从 pending 转为 fulfilled/rejected,且不可逆转,这是异步操作确定性的基础保障
  2. 微任务调度机制 所有回调必须通过微任务(queueMicrotask)执行,确保在同步代码之后、渲染之前执行,保证执行时序正确性
  3. 递归解析协议 通过 resolvePromise 函数递归处理 thenable 对象,兼容各种 Promise 实现,这是 A+ 规范的核心要求
  4. 链式传播机制 每个 then 都返回新 Promise,形成独立状态链,实现值/异常的逐级传递和错误冒泡处理
  5. 安全防护设计 循环引用检测防止无限递归,called 标志位防止多次调用,确保程序的健壮性和可靠性
  6. 值穿透实现原理 非函数参数时创建默认回调函数:value => valuereason => { throw reason },实现值/异常的自动传递

设计本质:状态机 + 回调队列 + 递归解析,通过 15 条规范解决异步编程的时序控制、错误处理、值传递等核心问题

代码流程#

flowchart TD
    A[new Promise] --> B[执行executor]
    B -->|resolve| C[状态改为fulfilled]
    B -->|reject| D[状态改为rejected]
    C --> E[执行onFulfilled回调]
    D --> F[执行onRejected回调]
    E --> G[处理返回值]
    F --> G
    G --> H[根据返回值处理新Promise]
    H --> I[链式调用]

代码实现#

const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
function isObject(value) {
const type = typeof value;
return value !== null && (type === "function" || type === "object");
}
function resolvePromise(promise, x, resolve, reject) {
if (promise === x) {
reject(new TypeError("Chaining cycle detected the promise #<Promise>"));
}
if (isObject(x)) {
var then;
try {
then = x.then;
} catch (error) {
reject(error);
}
if (typeof then === "function") {
var called = false;
try {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}
class MyPromise {
status = PENDING;
data = null;
#onFulfilledCallbacks = [];
#onRejectedCallbacks = [];
#resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.data = value;
while (this.#onFulfilledCallbacks.length) {
this.#onFulfilledCallbacks.shift()(value);
}
}
};
#reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.data = reason;
while (this.#onRejectedCallbacks.length) {
this.#onRejectedCallbacks.shift()(reason);
}
}
};
constructor(executor) {
try {
executor(this.#resolve, this.#reject);
} catch (error) {
this.#reject(error);
}
}
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
const promise = new MyPromise((resolve, reject) => {
const resolved = () => {
queueMicrotask(() => {
try {
const x = onFulfilled(this.data);
resolvePromise(promise, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
const rejected = () => {
queueMicrotask(() => {
try {
const x = onRejected(this.data);
resolvePromise(promise, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
if (this.status === PENDING) {
this.#onFulfilledCallbacks.push(resolved);
this.#onRejectedCallbacks.push(rejected);
}
if (this.status === FULFILLED) {
resolved();
}
if (this.status === REJECTED) {
rejected();
}
});
return promise;
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
return this.then(
(value) => MyPromise.resolve(onFinally()).then(() => value),
(reason) =>
MyPromise.resolve(onFinally()).then(() => {
throw reason;
})
);
}
static resolve(value) {
return new MyPromise((resolve, reject) => {
value instanceof MyPromise ? value.then(resolve, reject) : resolve(value);
});
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
static withResolver() {
const result = {};
result.promise = new MyPromise(($$resolve, $$reject) => {
result.resolve = $$resolve;
result.reject = $$reject;
});
return result;
}
}

业务场景#

  1. 异步流程控制:解决回调地狱,使异步代码更清晰
  2. 接口请求顺序:处理多个接口的串行/并行请求
  3. 错误统一处理:通过 catch 统一捕获整个链中的错误
  4. 数据依赖处理:处理前后端数据依赖关系
  5. 微任务调度:在渲染前执行关键逻辑(如状态更新)

性能考量: Promise 实现需要高效的微任务调度机制 避免深层递归导致的栈溢出 内存管理(及时清理回调队列)

相似题目#

  1. 实现 Promise.all(难度:中等)
    • 核心:处理多个 Promise 的并行执行
  2. 实现 Promise.race(难度:中等)
    • 核心:首个 Promise 完成即返回
  3. 实现 Promise.allSettled(难度:中等)
    • 核心:收集所有 Promise 的最终状态
  4. 实现 async/await(难度:困难)
    • 核心:Generator + Promise 的语法糖实现
  5. 实现并发控制器(难度:困难)
    • 核心:Promise + 队列控制并发数量
JavaScript 实现 Promise A+ 规范
https://website-truelovings-projects.vercel.app/posts/code/javascript/javascript-实现-promise-a-规范/
作者
欢迎来到StarSky的网站!
发布于
2025-08-13
许可协议
CC BY-NC-SA 4.0