Promise 是状态机,含 pending、fulfilled、rejected 三种单向流转状态;构造函数同步执行 executor,通过 resolve/reject 改变状态;then 必须异步执行回调并返回新 Promise;核心是 [[Resolve]] 过程,处理值穿透与 Promise 解析。

Promise 构造函数与三种状态
Promise 本质是一个状态机,必须严格维护 pending(等待)、fulfilled(成功)、rejected(失败) 三种状态,且状态只能单向流转:pending → fulfilled 或 pending → rejected,不可逆。构造函数接收一个执行器函数 executor,它立即同步执行,并传入 resolve 和 reject 两个函数作为参数。
手写时需注意:
- 状态用私有变量(如
_state)保存,初始为"pending" -
resolve(value)只在_state === "pending"时才更新状态为"fulfilled"并保存_value = value -
reject(reason)同理,设为"rejected"并保存_reason = reason - 若 executor 抛错,应直接
reject(e)
then 方法与微任务队列
then(onFulfilled, onRejected) 必须返回一个新的 Promise,实现链式调用。关键点在于:无论当前 Promise 处于什么状态,回调都必须异步执行(即放入微任务队列),以保证执行时机统一 —— 这是 Promises/A+ 规范第 2.2.4 和 3.1 节强制要求。
常见做法是使用 queueMicrotask(现代环境)或降级用 Promise.resolve().then 模拟微任务:
立即学习“Java免费学习笔记(深入)”;
- 若当前是
fulfilled状态,把onFulfilled(_value)包进微任务中执行 - 若当前是
rejected状态,同理执行onRejected(_reason) - 若仍是
pending,需将回调暂存到数组(如_onFulfilledCbs),等后续 resolve/reject 时再批量触发
值穿透与 Promise 解析过程(`[[Resolve]]`)
Promises/A+ 最核心也最易错的部分是 Promise 解析过程(规范中叫 [[Resolve]](promise, x))。它定义了当 then 的回调返回值 x 是一个 Promise 或类 Promise 对象时,如何正确“展开”并移交控制权。
手写时需在 resolve 函数内部做判断:
- 若
x === promise,抛出TypeError(防止自己 resolve 自己) - 若
x是对象或函数,尝试取其then属性;若取值报错,用该错误 reject 当前 promise - 若
then是函数,则以x.then(resolve, reject)调用它,并确保只调用一次(用called标志位防重复) - 否则(x 是普通值),直接
fulfill(promise, x)
这个逻辑要完整复现,不能省略任何分支,否则无法通过官方测试套件 promises-aplus-tests。
其他必要细节
要通过全部 Promises/A+ 测试,还需处理几个边界情况:
-
then的两个参数必须可选,未传时要透传(onFulfilled = v => v,onRejected = r => { throw r }) -
catch只是then(undefined, onRejected)的语法糖,可直接复用 -
Promise.resolve(value)需按 [[Resolve]] 规则处理value,而非简单返回新 Promise -
Promise.reject(reason)直接返回已拒绝的 Promise 即可 - 所有错误(包括 executor 抛错、取 then 报错、回调执行异常)都必须导致 Promise 被 reject
不复杂但容易忽略。


















