bigbigbo / issue-blog

bloooooooooog
15 stars 0 forks source link

[译]Promises/A+ 标准 #8

Open bigbigbo opened 5 years ago

bigbigbo commented 5 years ago

Promises/A+ 标准

_20190214092805

一个可靠的、可交互的 JavaScript Promises 开放标准 ——供实现者参考

一个 promise 表示一个异步操作的最终结果。和 promise 交互的主要方式是通过它的 then 方法,通过在 then 方法中注册回调函数来接收 promise 的最终值或者无法实现的原因(拒因)。

本规范详尽描述了 then 方法的行为,为所有 Promises/A+ 的实现提供了一个可交互的基础。因此,该规范将是非常稳定的。尽管 Promises/A+ 组织 可能会偶尔通过修正(向后兼容的 minor 版本)该规范来解决一些新发现的边界情况。只有经过仔细的考虑、讨论和测试之后,我们才会整合出一个大的或向后不兼容的版本。

Promises/A+ 澄清了早期的 Promises/A 提案的行为条款,扩展了一些内容并省略了未明确说明或有问题的部分。

最后,核心的 Promises/A+ 规范不涉及如何create(创建)fulfill(履行)reject(拒绝) promises,而是选择专注于提供一种可交互的 then 方法。未来在配套规范中的工作可能会涉及这些主题。

1. 名词解释

译者注: promisethenable 很像,区别就在于 then 方法是否严格符合本规范的定义,例如:

const obj = {
then() {
console.log("I'm not a promise")
}
}

只能称 obj 是一个 thenable 而不能称其为promise,因为它的 then 方法不符合本规范的行为描述。
reason 在之后都称之为为拒因

2. 要求

2.1 Promise 状态

一个 promise 的状态必须是 pendingfulfilledrejected三种状态中的一种。

注意:不可变 意味着恒等(即 ===),但不意味着深度不可变。

译者注:当值或者拒因为为引用类型时,只要其引用地址相同即可。

2.2 then 方法

一个 promise 必须提供一种方法来访问其当前的最终值或者拒因。

一个 promisethen 方法接收两个参数:

promise.then(onFulfilled, onRejected)

2.3 Promise 决策程序

Promise 决策程序(promise resolution procedure) 是一个抽象的操作,将 promise 和值作为输入,用代码表示为 [[Resolve]](promise, x)。如果 x 是一个 thenable,则该程序会尝试让 promise 接受 x 的状态,我们假设 x 的行为至少像一个 promise。 否则 promise 则以 x 为最终值直接执行。

这种对 thenable 的处理使得 promise 的实现更加灵活,只要暴露出符合Promises/A+的规范的 then 方法即可。它还允许 Promises/A+兼容不合规范的实现。

运行[[Resolve]](promise, x),将执行以下几种步骤:

如果一个 promise 在一条 由 thenable 组成的循环链中被 resolved,则会导致[[Resolve]](promise, thenable) 执行 [[Resolve]](promise, thenable),造成无限循环。我们鼓励去检测由此导致的错误,并以 TypeError 拒绝执行 promise,但这不是必须的。[3.6]

附录

3.1

这里的 platofrm code 是指引擎、环境和 promise 实现代码。实际上,这一要求确保 onFulfilledonRejected 是异步执行,并且是在 then 所被调用的那一轮的事件循环之后的新执行栈中执行。这边可以使用 setTimeout 或者 setImmediate 这类的宏任务(macro-task)实现或者使用 MutationObserverprocess.nextTick 这类的微任务(micro-task)去实现。因为promise的实现被认定为平台代码,他可能包含自身的任务队列。

3.2

也就是说,在严格模式下,this 值可能会是undefined,在非严格模式下,this 指向全局对象。

3.3

允许实现 promise2 === promise1,前提是必须实现所有要求。并且每个实现都应该记录它是否会产生及在什么条件下会产生 promise2 === promise1

3.4

只有符合当前规范的 x 才能被称为真正的 promise

3.5

首先存储对 x.then 的引用,然后测试该引用,然后调用该引用的过程应该避免对 x.then 属性的多次访问。此类预防措施对于确保访问属性的一致性非常重要,访问属性的值可能会在检索过程中发生变化。

3.6

实现不应该去设置 thenable 链的最大长度,并且去假定调用超过了设置的最大长度就是无限循环的调用。只有真正的递归调用才会抛出 TypeError,如果 thenable 链上的每一个 thenable 对象都不相同,那他就应该无限调用下去。