Promises/A+ 标准翻译

Posted 准时不早退の小森

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promises/A+ 标准翻译相关的知识,希望对你有一定的参考价值。

Promises/A+

为使用者提供可靠的、可协作的JavaScript Promises的一个开放标准

​ 一个promise表示一个异步操作的最终结果。和一个promise交互的主要方式是通过注册了回调函数的then方法,其中回调函数能够获取promise最终的值或者该promise无法执行的原因。

​ 此规范详述了提供了then方法的行为,所有遵循Promises/A+规范的promise实现均可将本标准作为参照基础来实施then方法。因此此规范必须十分稳定。尽管Promises/A+组织可能偶尔做向后兼容的小小改变来修改这一规范,从而解决新发现的边界情况,我们只在谨慎地考虑、讨论和测试后,整合一些大的或是不向后兼容的变化。

​ 从历史上看,Promises/A+阐明了更早的Promises/A建议的行为条例,将其扩展为包含实际上存在的行为,并且删减了在特殊情况下和有问题的部分。

​ 最后,核心的Promises/A+规范不涉及处理如何创建,执行或是拒绝promise,而是选择聚焦于提供一个可协作的then方法。未来的其他规范可能会涉及到这些方面。


1.术语

1.1. “promise”是一个具有then方法的对象或函数,其中then方法遵循此规范。

1.2. "thenable"是一个定义了then方法的对象或函数。

1.3. "value"是一个合法的javascript值(包括undefined,一个thenable或是一个promise)。

1.4. "exception"是一个使用throw声明被丢弃的value。

1.5. "reason"是一个指明为什么一个promise被拒绝的value。

2.要求

2.1. Promise 状态

一个promise必须在下列三种状态之一:pending(待决),fulfilled(完成)或者rejected(拒绝)。

2.1.1. 当promise状态为pending:

​ 2.1.1.1. 可能转换到fulfilled或者rejected状态。

2.1.2. 当promise状态为fulfilled:

​ 2.1.2.1. 一定不会转换到任何其他状态。

​ 2.1.2.2. 一定有一个不能改变的value。

2.1.3. 当promise状态为rejected时:

​ 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. onFulfilledonRejected都是可选参数:

​ 2.2.1.1. 如果onFulfilled不是一个函数,它应当被忽略。

​ 2.2.1.2. 如果onRejected不是一个函数,它应当被忽略。

2.2.2. 如果onFulfilled是一个函数:

​ 2.2.2.1. 它一定在promise fulfilled后才被调用,将promise的value作为其第一个参数。

​ 2.2.2.2. 它一定不会在promise fulfilled前被调用。

​ 2.2.2.3. 它的调用次数不会超过一次。

2.2.3. 如果onRejected是一个函数:

​ 2.2.3.1. 它一定在promise rejected后才被调用,将promise的reason作为其第一个参数。

​ 2.2.3.2. 它一定不会在promise rejected前被调用。

​ 2.2.3.3. 它的调用次数不会超过一次。

2.2.4. onFulfilled 或者onRejected当且仅当执行环境堆栈只包含平台代码时可以被调用。[见3.1]

2.2.5. onFulfilledonRejected必须以函数的方式被调用(例如:不包含this value)。

2.2.6. then在同一个promise中可能被多次调用。

​ 2.2.6.1. 如果/当promise被fulfilled后,所有相应的onFulfilled调用必须按照对then原始调用的顺序 执行。

​ 2.2.6.2. 如果/当promise被rejected后,所有相应的onFulfilled调用必须按照对then原始调用的顺 序执行。

2.2.7. then必须返回一个promise。[见3.3]

promise2=promise1.then(onFulfilled,onRejected);

​ 2.2.7.1. 如果onFulfilled或者onRejected返回一个value x,执行以下promise解决过程:

​ [[Resolve]](promise2,x)

​ 2.2.7.2. 如果onFulfilled 或者onRejected抛出一个 exception epromise2必须以e为reason来被rejected。

​ 2.2.7.3. 如果onFulfilled不是一个函数,同时promise1被fulfilled,promise2必须使用和promise1相同的value被fulfilled。

​ 2.2.7.4. 如果onRejected不是一个函数,同时promise1被fulfilled,promise2必须使用和promise1相同的value被rejected。

2.3 Promise解决过程

promise解决过程表示为[[Resolve]](promise,x),是以一个promise和一个value为输入的抽象操作。如果x是thenable的,同时x表现的有些像一个promise,那么解决过程试图让promise接受x的状态。否则,解决过程用value x来fulfill promise。

只要promise的实现暴露了一个遵循Promises/A+的then方法,这种thenable的特性就会使得promise的实现更具通用性,同时使得遵循了Promises/A+的promise实现能和未遵循但有可用then方法的promise实现共存。

为了运行[[Resolve]](promise,x),执行以下步骤:

2.3.1. 如果promisex指向同一个对象,那么以TypeError作为reason来reject promise

2.3.2 如果x是一个promise,接受它的状态[见3.4]:

​ 2.3.2.1. 如果x处于pending状态时,在x处于fulfilled或者rejected状态之前,promise必须一直保持 pending状态。

​ 2.3.2.2. 如果/当x处于fulfilled状态时,使用同样的value来fulfill promise

​ 2.3.2.3. 如果/当x处于rejected状态时,使用同样的reason来reject promise

2.3.3. 如果x是一个对象或者函数,

​ 2.3.3.1. 让then变为x.then[见3.5]

​ 2.3.3.2. 如果取x.then的值导致了一个exception e的抛出,将e作为reason来reject promise

​ 2.3.3.3. 如果then是一个函数,将x作为this来调用它,第一个参数为resolvePromise,第二个参 数为rejectPromise,其中:

​ 2.3.3.3.1. 如果/当resolvePromise被一个value y调用,运行[[Resolve]](promise,y).

​ 2.3.3.3.2. 如果/当rejectPromise被一个reason r调用,用r来reject promise

​ 2.3.3.3.3. 如果resolvePromiserejectPromise都被调用或者对同一参数进行了多次调用,则第 一次调用优先,其他所有调用都被忽略。

​ 2.3.3.3.4. 如果调用then抛出了一个exception e

​ 2.3.3.3.4.1 如果resolvePromise或者rejectPromise已经被调用过了,则无视。

​ 2.3.3.3.4.2. 否则,以e为reason来reject promise

​ 2.3.3.4. 如果then不是一个函数,用x来fulfill promise

2.3.4. 如果then不是一个对象或函数,用x来fulfill promise

如果一个promise使用参与了一个循环thenable链的thenable变为resolved,例如[[Resolve]](promise,thenable)的循环性质最终导致[[Resolve]](promise,thenable)被再次调用,遵循上述算法将导致无限递归。鼓励但不强制要求实现检测这样的递归,并以提示信息的TypeError 作为reason来reject promise

3.注释

3.1. 这里的平台代码指引擎,环境和promise的实现代码。实际上,这个要求确保了在then被调用的那一轮事件循环之后的新栈中,onFulfilledonRejected异步执行。可以使用例如setTimeoutsetImmediate的宏任务机制,或者例如MutationObserverprocess.nextTick的微任务机制来实现。由于promise实现本身就是平台代码,可能自身已经包含了一个在其中调用处理程序的任务调度队列。

3.2. 在严格模式下,它们的thisundefined;在非严格模式下,它是一个全局对象。

3.3. 在满足所有要求的情况下实现可能允许promise1===promise2,每个实现都应记录是否允许以及在什么条件下允许promise2===promise1

3.4. 通常,只有在x符合当前实现时,我们才认为它是真正的promise。这一条款允许那些特定实现方式接受已知符合要求的promises状态。

3.5. 这一步首先存储了对x.then的引用,接着测试了这个引用,随后调用这个引用,避免对于x.then属性的多次访问。这一预防措施对于确保访问器属性的一致性非常重要,因为访问器属性值可能在检索间改变。

3.6. 实现在thenable链的深度上不应该设置任意限制,并假定超出这一任意限制后将无限递归。只有真正的循环应该导致一个TypeError;如果遇到了一条无限长的链上thenable各不相同,正确的行为是一直递归下去。



翻译此标准是为了便于自己后续的实现,同时加深对于Promises/A+标准的理解。按个人阅读习惯,在翻译中保留了一些在标准中解释过的专有术语。个人水平不足,翻译可能存在一些问题,若有不当之处还望指正,谢谢!

以上是关于Promises/A+ 标准翻译的主要内容,如果未能解决你的问题,请参考以下文章

如何将此 JavaScript 代码片段翻译成 Parenscript?

100 行代码实现 Promises/A+ 规范

Promises/A+规范

We have a problem with promises

MP4box对DASH支持 翻译

mongoose 文档 Promises