「翻译练习」Promises/A+

2019-04-09  本文已影响0人  这名字真不对

一个由开发者为开发者提供的健全、互操作(interoperable)的JavaScript Promise 标准

互操作性指一种不同系统或组织之间可以协同工作的能力。在这里可以理解为只要符合该标准的的Promise实现,在语法上能够相互调用。

promise表示异步操作的最终结果。then方法是promise主要的交互方法,它通过注册回调函数,接收promise的最终结果或promise不能被履行(fulfilled)的原因。

这份文档详细说明了then方法的行为,提供了可互操作的基础,所有符合Promises/A+规范的都可以以这份标准实现。因此,这份标准非常稳定。尽管Promises/A+组织可能偶尔为了解决新发现的极端情况修改该规范,进行细微的修改,并向后兼容,我们会经过仔细考虑讨论和测试,才会整合较大的更改或向后不兼容的变更。

从过去的历史来看,Promises/A+解释了Promise/A 提案的早期的条款,并拓展了它,以解决早期不清楚的、有问题的部分。

最后,Promises/A+规范的核心没有涉及如何构建,履行(fufill),拒绝(reject)承诺,而是专注于提供可互操作的then方法。未来,关于规范的工作可能会涉及这些部分。

1. 术语

1.1. "promise" 是一个有符合该规范then方法的对象(object)或函数(function)。
1.2. "thenable" 是一个定义then方法的对象(object)或函数(function)。
1.3. "value" 是一个合法的JavaScript值 (包含undefined,thenablepromise)。
1.4. "exception" 是使用throw语句抛出的值。
1.5. "reason" 是一个包含promise为何被拒绝原因的值。

2. 要求

2.1 Promise 状态

一个promise必须处于三种状态之一:pending,fulfilled,rejected

2.1.1 当pending时,promise:

2.1.2 当fulfilled时,promise:

2.1.3 当rejected时,promise:

这里的不可改变指的是(比如两个值===),但不意味着深度不可变(比如const声明下的对象)。

2.2 then 方法

一个promise必须提供then方法用于接受当前或最终的值或原因。
一个promisethen方法接受两个参数:

promise.then(onFufilled, onRejected)

2.2.1 onFufilledonRejected都为可选参数
2.2.1.1 如果onFufilled不是函数,必须被忽略
2.2.1.2 如果onRejected不是函数,必须被忽略

2.2.2 如果onFufilled是一个函数

2.2.3 如果onRejected是一个函数

2.2.4 onFufilledonRejected 在执行环境堆栈只包含平台代码之前不得调用[3.1]

2.2.5 onFufilledonRejected 必须为函数形式调用,比如默认情况下函数调用时this值为undifined(比如fnc();)

2.2.6 then在同一个promise内可以调用多次

2.2.7 then 方法必须返回一个promise[3.3]
promise2 = promise1.then(onFufilled, onRejected)

2.3 Promise Resolution Procedure(PRP)

PRP是一个抽象的操作,以一个promise和值(value)作为参数输入,表示为[[Resolve]](promise, x)。如果xthenable对象,假设x的行为和promise对象有一点相似,尝试让promise处理x的状态。否则,x作为值履行(fulfills)promise

这种处理thenables的方式使得各种promise的实现可以互通,只要它们开放出一个与Promise/A+协议兼容的 then 方法即可。。它也允许Promises/A+的实现"接守"(原文"assimilate",吸收)那些不符合规范但合理的then方法。

[[Resolve]](promise, x),表现为以下步骤(以下的promise,x):
备注:下面的promise x分别表示这里的两个值

2.3.1 如果promisex引用同一个对象(循环引用),使用TypeError作为理由拒绝promise

2.3.2 如果x是一个promise实例,使用它的状态[3.4]:

2.3.3 其他情况,如果x是一个对象或者函数:

2.3.4 如果x不是对象或函数,以x为值 fulfill promise

如果一个promise对象被一个处于循环thenable链中的thenable对象解决(resolve),由于 [[Resolve]](promise, thenable)的递归本质会使得其再次被调用,按照上面的算法,这种情况将导致无限递归。本规范鼓励实现检测这种递归情况的出现,并使用带有一定信息的 TypeError 作为原因拒绝执行 promise [3.6],但规范不对此检测做强制要求。

3. 备注

3.1 这里“平台代码”指的是引擎(engine)、环境(environment)以及 promise 的实现代码(implementation code)。实际上,这个要求确保了onFulfilledonRejected方法能够异步执行,即在调用then方法的那个事件循环之后的新执行栈中异步执行。这个要求可以通过“宏任务(macro-task)”机制(例如 setTimeout 或者 setImmediate)或者“微任务(micro-task)”(例如MutationObserver或者process.nextTick)来实现。由于promise的实现本身也被认为是“平台代码”,所以其自身可能也会包含一种任务调度队列或者“trampoline”控制结构来对其处理程序进行调用。

3.2 也就是说,this的值,在严格模式(strict)下为undefined;在非严格模式下为全局对象(global object)。

3.3 在满足所有要求的情况下,实现中可能允许promise2 === promise1。每个实现都需要说明其是否允许出现promise2 === promise1,以及在何种条件下出现。

3.4 通常来说,只有当x是从当前实现中定义出来的,我们才知道它是否是一个真正的promise对象。这条规则允许使用特定实现中的方法去采用符合规范的promise对象的状态。

3.5 这一步中先会存储一个指向x.then的引用,然后测试该调用,之后调用该引用,避免对x.then属性的多处访问。这些预防措施对于保证访问器属性的一致性至关重要,因为其值可能在多次取值期间发生变化。

3.6 实现不应该限定thenable链的深度,并假设只要超出了限制,递归就是无限的。只有真正的循环递归才应导致一个TypeError错误;如果一条无限长链上的thenable对象各不相同,那么无限递归下去就是正确的行为。

上一篇下一篇

猜你喜欢

热点阅读