实现者为实施者提供开放的标准,实现可靠,可互操作的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作为promise2rejected的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必须保持待处理状态,直到xfulfilled或rejected为止。 - 2.3.1.2. 如果/当
xfulfilled,则promise使用相同的value fulfilled。 - 2.3.1.3. 如果/当
xrejected,请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作为promisefulfilled的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;如果遇到无限的不同的可能的链,那么永远递归就是正确的行为。