实现者为实施者提供开放的标准,实现可靠,可互操作的JavaScript Promise.
Promise表示异步操作的最终结果。与promise进行交互的主要方式是通过其then
方法,该方法注册回调以接收promise
的最终值或无法履行promise
的原因。
该规范详细说明了该then
方法的行为,提供了一个可互操作的基础,可以依赖所有Promises/A+符合的promise实现来提供。因此,应该认为规范非常稳定。尽管Promises/A+组织可能会偶尔修改此规范,并进行微小的向后兼容更改以解决新发现的极端情况,但只有经过仔细考虑,讨论和测试后,我们才会集成大型或向后不兼容的更改。
从历史上看,Promises/A+澄清了早期Promises/A提案的行为条款,将其扩展到涵盖事实上的行为并省略了未指明或有问题的部分。
最后,核心Promises/A+规范没有涉及如何创建,实现或拒绝Promise,而是选择专注于提供可互操作的then
方法。配套规范中的未来工作可能涉及这些主题。
1.术语
- 1.1. “promise”是具有
then
方法的对象或函数,其行为符合本规范。 - 1.2. “thenable”是定义
then
方法的对象或函数。(promise是thenable对象) - 1.3. “value”是任何合法的JavaScript值(包括
undefined
,thenable或promise)。 - 1.4. “exception”是使用
throw
语句抛出的值。 - 1.5. “reason”是promise失败的原因。
2.要求
2.1.Promise状态
Promise必须处于以下三种状态之一: pending, fulfilled 或 rejected。
2.1.1. pending状态时,Promise:
- 2.1.1.1. 可以过渡到fulfilled或rejected的状态。
2.1.2. fulfilled状态时,Promise:
- 2.1.2.1. 不得过渡到任何其状态。
- 2.1.2.2. 必须有一个值(value),绝不能改变。
2.1.3. rejected状态时,Promise:
- 2.1.3.1. 不得过渡到任何其状态。
- 2.1.3.2. 必须有一个原因(reason),绝不能改变。
在这里,“绝不能改变”意味着不可改变的身份(即===
),但并不意味着深度的不变性。(引用类型地址不变)
2.2.then
方法
promise必须提供一种then
方法来访问其当前或最终的value或reason。
promise的then
方法接受两个参数:
promise.then(onFulfilled, onRejected)
2.2.1. 这两个onFulfilled
和onRejected
可选的参数:
- 2.2.1.1. 如果
onFulfilled
不是函数,则必须忽略它。 - 2.2.1.2. 如果
onRejected
不是函数,则必须忽略它。
2.2.2. 如果onFulfilled
是一个函数:
- 2.2.2.1. 它必须在
promise
完成后调用,promise
的value作为第一个参数。 - 2.2.2.2. 在
promise
完成之前不得调用它。 - 2.2.2.3. 它不能被多次调用。
2.2.3. 如果onRejected
是一个函数:
- 2.2.3.1. 它必须在
promise
被拒绝后被调用,promise
的reason作为第一个参数。 - 2.2.3.2.
promise
拒绝之前不得调用它。 - 2.2.3.3. 它不能被多次调用。
2.2.4. onFulfilled
或者onRejected
在执行上下文堆栈仅包含平台代码之前不得调用。(链式调用,then方法返回一个新的promise对象,需要等新promise对象实例化结束后才能调用then的回调函数) 3.1 。
2.2.5. onFulfilled
并且onRejected
必须作为函数调用(即没有this
值)。 3.2
2.2.6. then
可以在同一个promise
上多次调用。
- 2.2.6.1. 如果/当
promise
是fulfilled状态,则所有相应的onFulfilled
回调必须按原始顺序执行then
。 - 2.2.6.2. 如果/当 promise是rejected状态,则所有相应的
onRejected
回调必须按原始的顺序执行then
。
2.2.7. then
必须返回一个promise
3.3 。
promise2 = promise1.then(onFulfilled, onRejected);
- 2.2.7.1.如果任一
onFulfilled
或onRejected
返回一个值x
(x
可能是promise
,所以需要增加处理函数),运行Promise
解决程序[[Resolve]](promise2, x)
。 - 2.2.7.2.如果
onFulfilled
或者onRejected
抛出异常e
,将e
作为promise2
rejected的reason。 - 2.2.7.3.如果
onFulfilled
不是一个函数并且promise1
已经完成,则promise2
必须使用与promise1
相同的value来fulfilled。 - 2.2.7.4.如果
onRejected
不是一个函数而promise1
被拒绝,promise2
必须与promise1
以同样的reason来rejected。
2.3.Promise解决程序
promise解决程序是一个函数,参数为一个promise和一个value,它表示为[[Resolve]](promise,x)
。如果x
是一个thenable(promise
),它会尝试promise
采用x
的状态,前提是x
行为至少有点像promise
。否则,它作为promise
的fulfilled的value返回。
对thenables的这种处理允许promise实现进行互操作,只要它们公开Promise/A+兼容then
方法即可。它还允许Promises/A+实现使用合理的then
方法“同化”不一致的实现。
要运行[[Resolve]](promise, x),请执行以下步骤:
2.3.1.如果promise
和x
引用同一个对象,请以promise TypeError
为reason来rejected。
2.3.2. 如果x
是promise
,采用其状态 3.4 :
- 2.3.2.1. 如果
x
待处理pending,则promise
必须保持待处理状态,直到x
fulfilled或rejected为止。 - 2.3.1.2. 如果/当
x
fulfilled,则promise
使用相同的value fulfilled。 - 2.3.1.3. 如果/当
x
rejected,请promise
以同样的reason rejected。
2.3.3.否则,如果x
是对象或函数:
- 2.3.3.1.让
then = x.then
。 3.5 - 2.3.3.2.如果检索属性
x.then
中抛出的异常的结果e
,将e
作为promise
的reason来rejected。 - 2.3.3.3.如果
then
是函数,将x
作为this
调用它,第一个参数resolvePromise
和第二个参数rejectPromise
,其中:- 2.3.3.3.1. 如果
resolvePromise
被调用并返回一个值y
(原理同x
,可能为promise
),则运行[[Resolve]](promise, y)
。 - 2.3.3.3.2. 如果/当
rejectPromise
被调用并是带一个reasonr
,将r
作为拒绝promise
的reason。 - 2.3.3.3.3. 如果这两个
resolvePromise
和rejectPromise
被调用,或多次调用相同的参数,则第一次调用优先,任何进一步的调用将被忽略。 - 2.3.3.3.4.如果调用
then
抛出异常e
:- 2.3.3.3.4.1. 如果
resolvePromise
或rejectPromise
已被调用,请忽略它。 - 2.3.3.3.4.2. 否则,将
e
作为promise
的rejected的reason。
- 2.3.3.3.4.1. 如果
- 2.3.3.3.1. 如果
- 2.3.3.4.如果
then
不是一个函数,将x
作为promise
fulfilled的value。
2.3.4. 如果x
不是一个对象或函数,将x
作为promise
的fulfilled的value。
如果使用参与循环可变链的thenable来解决promise,使得[[Resolve]](promise, thenable)
最终导致[[Resolve]](promise,thenable)
再次调用的递归性质,遵循上述算法将导致无限递归。鼓励但不要求实现以检测这种递归并拒绝promise
提供信息TypeError
作为原因。 3.6
3.笔记
-
3.1. 这里的“平台代码”意味着引擎,环境和promise实现代码。在实践中,此要求确保在调用事件循环并且使用新堆栈之后异步执行
onFulfilled
和onRejected
执行then
。这可以用“宏任务”机制实现,例如setTimeout
或者setImmediate
,或者用“微任务”机制,例如MutationObserver
或process.nextTick
。由于promise
实现被认为是平台代码,因此它本身可能包含一个任务调度队列或“trampoline”,其中调用处理程序。 -
3.2.也就是说,严格模式
this
将undefined
在其中;在草率模式下,它将成为全局对象。 -
3.3.
promise2 === promise1
只要实现满足所有要求,实现可以允许。每个实施应记录它是否可以生产promise2 === promise1
以及在什么条件下生产。 -
3.4. 一般来说,
x
如果它来自当前的实现,那么它只是一个真正的promise
。该子句允许使用特定于实现的方法来采用已知符合的promise
的状态。 -
3.5. 此过程首先存储引用
x.then
,然后测试该引用,然后调用该引用,避免多次访问该x.then
属性。这些预防措施对于确保访问者属性的一致性非常重要,访问者属性的值可能会在检索之间发生变化。 -
3.6. 实现应不设置thenable链的深度任何限制,并假设超出任何限制递归将是无限的。只有真正的周期才能导致
TypeError
;如果遇到无限的不同的可能的链,那么永远递归就是正确的行为。