对于实现者来说,这是一个开放标准,用于实现可靠的,可互操作的JavaScript Promise。
promise代表异步操作的最终结果。 与promise互动的主要方式是通过其_then_的方法,该方法注册回调以接收promise的最终值或promise无法执行(fulfill)的原因。
本规范详细介绍了then方法的行为,所有遵循Promise/A+实现的promise都可以以此为参照基础。本规范应该被认为是非常稳定的。虽然Promises/A+组织可能会偶尔修改此规范,但大都是微小且向下兼容的,主要为了处理一些新发现的边界情况。只有在仔细考虑,讨论和测试之后,我们才会大规模或后向不兼容的更改。
历史角度说,Promises/A+只是将先前Promises/A提案的行为建议阐明为明确的行为准则,并省略移除未指定或存在问题的内容。
最后,核心Promises/A+规范不涉及如何创建(create),执行(fulfill)或拒绝(reject)promise,而是选择专注于提供可通用的_then_方法。 未来的配套规范工作可能涉及其他内容。
1.1 “promise”是具有一个其行为符合本规范的_then_方法的对象或函数。
1.2 “thenable”是一个定义_then_方法的对象或函数。
1.3 “value”是任何合法的JavaScript值(包括_undefined_, thenable或promise)。
1.4 “exception”是使用_throw_语句抛出的值。
1.5 “reason”是一个用来表明promise被拒绝的原因的值。
promise必须处于以下三种状态中的一种:pending,fulfilled,rejected。
- 可能转换到fulfilled状态或rejected状态。
- 不能再转换到其他状态。
- 必须有一个不能改变的值。
- 不能再转换到其他状态。
- 必须有一个不能改变的原因。
在这里,“不能改变”是指不可改变的身份(即===),但并不意味着深层不可变。
promise必须提供一个_then_方法来获取其当前值或最终值或原因。
promise的_then_方法接受两个参数:
promise.then(onFulfilled, onRejected)
- 如果_onFulfilled_不是函数,则必须忽略它。
- 如果_onRejected_不是函数,则必须忽略它。
- 必须在promise状态为fulfilled后被调用,promise的值作为第一个参数。
- 在promise状态为fulfilled前不能被调用。
- 不能被多次调用。
- 必须在promise状态为rejected后被调用,promise的reason是它的第一个参数。
- 在promise状态为rejected前不能被调用。
- 不能被多次调用。
- 当promise为fulfilled状态时,所有各自的_onFulfilled_回调必须按照其注册的顺序执行_then_。
- 当promise为rejected状态时,所有各自的_onRejected_回调必须按照其注册的顺序执行_then_。
promise2 = promise1.then(onFulfilled, onRejected);
- 如果_onFulfilled_或_onRejected_返回一个值x,则运行下面promise处理程序 [Resolve]。
- 如果_onFulfilled_或_onRejected_抛出异常e,promise2必须为rejected状态并以e为原因。
- 如果_onFulfilled_不是函数并且promise1为fulfilled状态,那么promise2必须为fulfilled状态并与promise1值相同。
- 如果_onRejected_不是函数并且promise1为rejected状态,那么promise2必须为rejected状态并与promise1原因相同。
promise处理程序是一个抽象操作,输入为一个promise和一个值,我们表示为[[Resolve]](promise, x)。如果x是一个thenable且有点像一个promise,处理程序尝试promise采用x的状态。 否则,处理程序用值x执行promise。
thenable的特性使得promise的实现更通用:只要其暴露出一个遵循Promise/A+的_then_方法即可;这同时也使遵循Promise/A+规范的实现可以与那些不太规范但还可用的实现不相冲突。
要运行[[Resolve]](promise, x),请执行以下步骤:
- 如果x为pending状态,promise必须保持pending状态直到x为fulfilled或rejected。
- 如果x为fulfilled状态,promise为fulfilled状态时与x同样的值。
- 如果x为rejected状态,promise为fulfilled状态时与x同样的原因。
- 把x.then赋给then
- 如果检索属性x.then导致抛出异常e,promise为rejected状态并以e为原因。
- 如果then是函数,则使用x作为this调用函数,第一个参数为resolvePromise,第二个参数为rejectPromise,其中:
- 当resolvePromise以值y调用,运行[[Resolve]](promise, y)。
- 当rejectPromise以原因r被调用时,promise以r为原因拒绝。
- 当resolvePromise和rejectPromise都被调用,或者对同一个参数进行多次调用,则第一次调用优先,并且任何进一步调用都会被忽略。
- 如果调用_then_抛出异常e:
- 如果resolvePromise或rejectPromise已被调用,请忽略它。
- 否则,promise以e为原因拒绝。
- 如果then不是函数,promise为fulfilled状态时以x为值。
- 如果x不是对象或函数,promise为fulfilled状态时以x为值。
如果一个promise是通过参与一个循环的thenable链来解决的,那么[[Resolve]](promise, thenable)的递归性质最终会导致[[Resolve]](promise, thenable)被再次调用, 上述算法将导致无限递归。鼓励实现,但不是必需的,若检测到这种递归,用一个_TypeError_信息来拒绝 promise。注[3.6]
这里“平台代码”是指引擎,环境和promise实现代码。 在实践中,这个要求确保_onFulfilled_和_onRejected_异步执行,在被调用的那一轮事件循环之后的新执行栈中执行. 这可以使用诸如setTimeout或setImmediate之类的“宏任务”机制或者使用诸如MutationObserver或process.nextTick之类的“微任务”机制来实现。 由于promise实现被认为是平台代码,因此它本身可能包含一个调用处理程序的任务调度队列。
也就是说,在严格模式下,this为undefined; 在非严格模式下,this将指向全局对象。
如果实现符合所有要求,实现可能允许promise2 === promise1。 每个实现应该记录它是否可以产生promise2 === promise1以及在什么条件下。
一般来说,如果 x 符合当前实现,我们才认为它是真正的 promise 。 这个规则允许使用具体实现方式来采用符合已知要求的 promise 状态。
先s是存储对x.then的引用,然后测试该引用并调用,以避免对x.then属性的多次访问。 这样的预防措施对于确保访问属性的一致性非常重要,因为值可能会在检索之间发生变化。
实现不应该对 thenable 链的深度设置任意限制,并且假定超出该任意限制递归将是无限的。 只有真正的循环引用应该导致TypeError; 如果遇到无限链是不同的 thenable ,永远递归是正确的行为。