手动实现 Promise 构造器需严格遵循 Promise/A+ 规范:状态三态不可逆(pending→fulfilled/rejected),executor 同步执行并用 try/catch 捕获异常;所有回调必须通过 queueMicrotask 微任务异步调度;then 返回新 Promise,支持值穿透与错误冒泡。

要手动实现一个支持“状态切换”与“微任务调度”的基础 Promise 构造器,关键在于两点:一是严格遵循 Promise/A+ 规范的状态不可逆性(pending → fulfilled 或 pending → rejected),二是确保所有回调都通过微任务异步执行(如 queueMicrotask 或 Promise.resolve().then),而非同步或宏任务。
状态管理:三态不可逆
Promise 实例必须维护内部状态(pending、fulfilled、rejected)和对应结果(value 或 reason)。状态一旦变更,就不可再修改:
- 构造时初始状态为
pending,value和reason均为undefined -
resolve(value)只在pending状态下生效,设为fulfilled并保存value -
reject(reason)同理,设为rejected并保存reason - 重复调用
resolve或reject应被静默忽略(靠状态判断拦截)
executor 必须同步执行
规范强制要求:传入 new MyPromise(executor) 的 executor 函数,必须在构造函数内立即、同步调用,不能包裹在 setTimeout、setImmediate 或任何异步上下文中:
- 正确写法:
executor(resolve, reject)直接出现在构造函数体中 - 错误写法:
setTimeout(() => executor(resolve, reject), 0)—— 这会导致 promises-aplus-tests 失败 - 若
executor抛出同步异常,应等价于调用reject(e),需用try/catch包裹
微任务调度:回调必须异步触发
无论 then 注册时 Promise 处于何种状态,其回调(onFulfilled 或 onRejected)都必须在当前任务结束后、下一个宏任务开始前执行。推荐使用 queueMicrotask:
- 当状态已变为
fulfilled,执行onFulfilled(value)时,需包裹在queueMicrotask(() => {...})中 - 同理,
rejected状态下执行onRejected(reason)也需微任务包装 - 若状态仍为
pending,则把回调存入队列(如onFulfilledCallbacks.push(() => {...})),待后续resolve/reject触发时统一用微任务执行 - 避免使用
setTimeout(..., 0)—— 它是宏任务,会破坏 Promise 链的执行顺序
.then 方法:返回新 Promise 并兼容状态流转
then 不修改原实例,而是返回一个全新的 Promise 实例,这是链式调用的基础:
- 无论当前 Promise 是
pending、fulfilled还是rejected,then都必须返回新 Promise - 若当前为
pending,将onFulfilled/onRejected推入对应回调队列 - 若已
fulfilled,用微任务执行onFulfilled(value),并将返回值交由resolvePromise处理(支持普通值、Promise、thenable) - 若已
rejected,同理处理onRejected(reason),错误需冒泡到新 Promise - 未传
onFulfilled时,默认透传value;未传onRejected时,默认抛出reason(实现错误冒泡)










