Promise/A+ 规范中文解读
一、简介
Promise/A+ 是一个开放、健全且通用的JavaScript Promise标准,由开发者制定并供开发者参考。其核心目标是定义then
方法的行为,确保不同Promise实现的互操作性。规范聚焦于异步操作的最终结果交互机制,而非Promise的创建、解决或拒绝方式。
二、术语
- Promise:拥有
then
方法且行为符合本规范的对象或函数。 - Thenable:定义
then
方法的对象或函数。 - 值(Value):任何合法的JavaScript值(包括
undefined
、thenable或Promise)。 - 异常(Exception):通过
throw
语句抛出的值。 - 拒因(Reason):Promise被拒绝时传递的原因。
三、 核心规范
3.1 Promise的状态
Promise必须处于以下三种状态之一:
- 等待态(Pending):可转换为兑现态(Fulfilled)或拒绝态(Rejected)。
- 成功态(Fulfilled):不可再改变状态;必须拥有一个不可变的终值(恒等性,即
===
判定)。 - 拒绝态(Rejected):不可再改变状态;必须拥有一个不可变的拒因(恒等性)。
3.2 then
方法
Promise必须提供then
方法以访问其终值或拒因:
promise.then(onFulfilled, onRejected)
3.2.1 参数规则
- 可选性
onFulfilled
和onRejected
均为可选参数,非函数类型需被忽略。
- 调用条件
onFulfilled
在Promise兑现后调用,接收终值作为首个参数,且仅调用一次。onRejected
在Promise拒绝后调用,接收拒因作为首个参数,且仅调用一次。
- 异步执行
- 回调需在执行栈仅含平台代码时调用(即异步执行,通常通过微任务队列实现)。
3.2.2 多次调用与顺序
- 同一Promise可多次调用
then
,回调按注册顺序执行。
3.2.3 返回值
then
必须返回新Promise(promise2
),其状态由以下规则决定:- 若回调返回普通值
x
,执行[[Resolve]](promise2, x)
。 - 若回调抛出异常
e
,promise2
需拒绝并传递e
。 - 若
onFulfilled
非函数且原Promise兑现,promise2
需以相同终值兑现。 - 若
onRejected
非函数且原Promise拒绝,promise2
需以相同拒因拒绝。
- 若回调返回普通值
3.3 Promise解决过程
抽象操作[[Resolve]](promise, x)
决定如何根据x
的类型处理Promise的状态:
3.3.1 步骤
- 循环引用检测
- 若
promise
与x
为同一对象,以TypeError
拒绝。
- 若
- 处理Promise实例
- 若
x
为Promise,直接继承其状态。
- 若
- 处理Thenable对象
- 若
x
为对象或函数:- 尝试获取
x.then
,若获取过程抛出异常e
,以e
拒绝Promise。 - 若
then
为函数,以x
为上下文调用,并传入resolvePromise
和rejectPromise
:- 若
resolvePromise(y)
被调用,递归执行[[Resolve]](promise, y)
。 - 若
rejectPromise(r)
被调用,以r
拒绝Promise。 - 仅首次调用生效,后续调用被忽略。
- 若
- 尝试获取
- 若
- 非Thenable值
- 若
x
非对象或函数,直接以x
兑现Promise。
- 若
3.3.2 循环引用处理
- 若检测到
thenable
链导致无限递归,鼓励(但不强制)实现以TypeError
拒绝。
四、注释与实现细节
- 平台代码:指引擎、环境及Promise实现本身的代码,确保回调异步执行(如通过微任务队列)。
- 严格模式:
onFulfilled
和onRejected
需作为普通函数调用(无this
绑定)。 - 历史兼容性:规范基于早期Promise/A提案,明确行为并剔除不明确或有问题的部分。
五、总结
Promise/A+规范通过标准化then
方法,为异步操作提供了可预测的行为模型。其核心在于状态机管理、回调调度及递归解决逻辑,确保了不同实现的互操作性。开发者可通过遵循此规范,构建健壮且一致的异步处理机制。
六、 参考与扩展
- 官方英文原版:
- Promises/A+ Specification
- 推荐实现库:
es6-promise
、bluebird
、Q.js
等均遵循此规范。