手动实现 Promise 容器需严格遵循 Promise/A+ 规范:①状态单向不可逆(pending→fulfilled/rejected),用私有属性和闭包保障不可变性;②then 回调必须通过 queueMicrotask 或 Promise.resolve().then 进行微任务调度,确保异步优先级;③then 链式返回新 Promise,支持值透传、Promise 扁平化及错误捕获。

要手动实现一个支持“静态状态切换”与“微任务调度”的 Promise 容器,核心在于两点:一是严格遵循 Promise/A+ 规范中对 pending → fulfilled 或 pending → rejected 单向不可逆状态切换的约束;二是确保 then 回调在当前宏任务结束后、下一个宏任务开始前,通过微任务(如 queueMicrotask 或 Promise.resolve().then)执行。
状态封装与不可变性控制
Promise 实例内部必须维护一个私有状态(status),初始为 "pending",仅允许一次变为 "fulfilled" 或 "rejected",之后任何尝试修改都应被忽略。
- 用闭包或
WeakMap存储实例私有状态,避免外部篡改 - 在
resolve/reject函数中,先检查当前状态是否仍为"pending",否则直接返回 - 状态变更后,立即保存终值(
value)或拒因(reason),供后续then消费
微任务队列的可靠接入
规范要求 then 的回调必须异步执行,且优先级高于 setTimeout(即属于微任务)。手动实现时不应依赖 setTimeout 或 setImmediate,而应使用浏览器/Node.js 环境原生支持的微任务机制:
- 首选
queueMicrotask(fn)(现代环境推荐,语义清晰) - 降级方案:用
Promise.resolve().then(fn)—— 注意不能用自身类,否则可能引发循环引用或未定义行为 - 避免在微任务中抛出未捕获错误,否则会触发全局
unhandledrejection,需包裹try/catch
then 方法的链式与透传逻辑
then 必须返回新 Promise 实例,并正确处理三种情况:同步返回值、返回 Promise、抛出异常。关键点包括:
- 无论当前实例处于什么状态(pending/fulfilled/rejected),
then都应返回新 Promise,并把回调推入对应队列(onFulfilledQueue/onRejectedQueue) - 若实例已确定状态,立即用微任务调度对应回调;若仍 pending,则暂存回调,待 resolve/reject 时统一触发
- 回调执行后,根据返回值决定新 Promise 的状态:
– 返回普通值 → 新 Promiseresolve该值
– 返回 Promise 实例 → 新 Promise 状态跟随它(即“扁平化”)
– 抛错 → 新 Promisereject该错误
基础骨架示例(精简可运行版)
以下为最小可行实现,不含完整错误边界和边缘 case,但覆盖核心机制:
class MyPromise {
#status = 'pending';
#value = undefined;
#reason = undefined;
#onFulfilledCbs = [];
#onRejectedCbs = [];
constructor(executor) {
const resolve = (value) => {
if (this.#status !== 'pending') return;
this.#status = 'fulfilled';
this.#value = value;
this.#onFulfilledCbs.forEach(cb => queueMicrotask(() => cb(value)));
};
const reject = (reason) => {
if (this.#status !== 'pending') return;
this.#status = 'rejected';
this.#reason = reason;
this.#onRejectedCbs.forEach(cb => queueMicrotask(() => cb(reason)));
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r; };
const next = new MyPromise((resolve, reject) => {
const handleFulfill = (value) => {
try {
const res = onFulfilled(value);
resolvePromise(next, res, resolve, reject);
} catch (e) {
reject(e);
}
};
const handleReject = (reason) => {
try {
const res = onRejected(reason);
resolvePromise(next, res, resolve, reject);
} catch (e) {
reject(e);
}
};
if (this.#status === 'fulfilled') queueMicrotask(() => handleFulfill(this.#value));
else if (this.#status === 'rejected') queueMicrotask(() => handleReject(this.#reason));
else {
this.#onFulfilledCbs.push(handleFulfill);
this.#onRejectedCbs.push(handleReject);
}
});
return next;
}
}
function resolvePromise(promise, x, resolve, reject) {
if (promise === x) {
return reject(new TypeError('Chaining cycle detected'));
}
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
let called = false;
try {
const then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
});
return;
}
} catch (e) {
if (called) return;
called = true;
reject(e);
return;
}
}
resolve(x);
}

















