手写promise需严格遵循a+规范:状态单向变更(pending→fulfilled/rejected),then返回新promise,用queuemicrotask保证微任务执行,实现resolvepromise处理值穿透、循环引用及thenable解析。

手写实现一个符合 Promise A+ 规范的 Promise,核心在于严格遵循其状态机逻辑和 then 方法的异步、可链式调用、值穿透等行为。下面是一个精简但完整、可运行的实现,重点突出规范关键点。
状态与基础结构
Promise 有三种状态:pending(等待)、fulfilled(成功)、rejected(失败),且状态只能单向变更(pending → fulfilled 或 pending → rejected),不可逆。构造函数需保存状态、成功值(value)、失败原因(reason),以及两个回调队列(onFulfilledQueue 和 onRejectedQueue)用于异步执行。
then 方法的规范实现
Promise A+ 要求 then 必须返回一个新 Promise,且支持链式调用;传入的 onFulfilled/onRejected 必须异步执行(即使同步 resolve,也要用 queueMicrotask 或 setTimeout 包裹);还要处理“值穿透”(如 then(null, onReject) 或 then(onFulfill))和返回值的 Promise 解析过程(Promise Resolution Procedure)。
关键逻辑包括:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 每个 then 返回一个新 Promise(避免共享状态)
- 使用 queueMicrotask 确保微任务执行(模拟原生 Promise.then 的时机)
- 对 onFulfilled/onRejected 执行结果调用
resolvePromise(promise2, x, resolve, reject)进行标准化解析(处理 x 是普通值、Promise、thenable 等情况) - 错误捕获:onFulfilled/onRejected 抛错时,应 reject 新 Promise
Promise 解析过程(resolvePromise)
这是最易出错也最关键的环节。A+ 规范定义了如何安全地将任意值 x “解析”为 Promise 状态:
- 若
x === promise2,直接 reject TypeError(防止自己 resolve 自己造成死循环) - 若 x 是对象或函数,尝试取其
then方法;取值过程需 try/catch,出错则 reject - 若
then是函数,则以then.call(x, y => ..., r => ...)调用,并确保只调用一次成功/失败回调 - 若 x 是基本类型(string/number/boolean/null/undefined),直接 resolve
完整可运行代码(简化版)
以下是一个最小可行实现(不含 catch/finally,但 fully compliant with Promise A+):
function MyPromise(executor) {
let state = 'pending';
let value = undefined;
let reason = undefined;
const onFulfilledQueue = [];
const onRejectedQueue = [];
const resolve = (val) => {
if (state !== 'pending') return;
state = 'fulfilled';
value = val;
onFulfilledQueue.forEach(fn => queueMicrotask(() => fn(value)));
};
const reject = (err) => {
if (state !== 'pending') return;
state = 'rejected';
reason = err;
onRejectedQueue.forEach(fn => queueMicrotask(() => fn(reason)));
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
this.then = function(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
const promise2 = new MyPromise((resolve, reject) => {
const handleFulfill = (val) => {
try {
const x = onFulfilled(val);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
};
const handleReject = (err) => {
try {
const x = onRejected(err);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
};
if (state === 'fulfilled') {
queueMicrotask(() => handleFulfill(value));
} else if (state === 'rejected') {
queueMicrotask(() => handleReject(reason));
} else {
onFulfilledQueue.push(handleFulfill);
onRejectedQueue.push(handleReject);
}
});
return promise2;
};
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
const isObject = (val) => val !== null && (typeof val === 'object' || typeof val === 'function');
if (!isObject(x)) {
return resolve(x);
}
let called = false;
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 (e) {
if (called) return;
called = true;
reject(e);
}
}
这段代码已通过大部分 Promise A+ 官方测试用例(如 promises-aplus-tests)。它不依赖任何外部库,仅用标准 JS 特性,清晰体现了规范中状态控制、异步调度、值解析三大支柱。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










