你该知道的promise(1):Promise/A+规范中英文对照翻译

127 阅读10分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 自 es6 推出promise以来,promise强大的异步处理功能被广大开发者认可并广泛使用,那么其实现逻辑真的都非常清楚吗?这里我断断续续花了几天的时间将Promises/A+ 规范结合自己的一丝丝理解和实践做了翻译,方便大家更加容易的来理解 promise 的真实情况。 Promises/A+原文

1. Terminology(术语)

1.1. “promise” is an object or function with a then method whose behavior conforms to this specification.

1.1. promise 是一个拥有 then 方法的对象或者函数,其行为准守此规范

1.2. thenable” is an object or function that defines a then method.

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

1.3. “value” is any legal JavaScript value (including undefined, a thenable, or a promise).

1.3. value 任意合法类型的JavaScript值(包括undefined, ”thenabel“ 或者 ”promise“)

1.4. “exception” is a value that is thrown using the throw statement.

1.4. exception 是由 throw 抛出的异常信息

1.5. “reason” is a value that indicates why a promise was rejected.

1.5. reason 是 promise 拒绝的标识值(拒因)

2. Requirements(需求)

2.1. Promise States

A promise must be in one of three states: pending, fulfilled, or rejected.

一个 promise 对象必须处于 pendingfulfilledrejected 三个状态之一

2.1.1. When pending, a promise:

2.1.1. 当一个promise对象处于 pending 状态:

 2.1.1.1. may transition to either the fulfilled or rejected state.

 2.1.1.1. 只能转变为 fulfilled 或者 rejected 状态

2.1.2. When fulfilled, a promise:

2.1.2. 当一个promise对象处于 fulfilled 状态:

 2.1.2.1. must not transition to any other state.

 2.1.2.1. 不能转变为任何状态

 2.1.2.1. must have a value, which must not change.

 2.1.2.1. 必须有一个不可变的值

2.1.3. When rejected, a promise:

2.1.3. 当一个promise对象处于 rejected 状态:

 2.1.3.1. must not transition to any other state.

 2.1.3.1. 不能转变为任何状态

 2.1.3.2. must have a reason, which must not change.

 2.1.3.2. 必须有一个不可变的据因

Here, “must not change” means immutable identity (i.e. ===), but does not imply deep immutability.

这里的不可变是指的可以恒等(也就是可以用 === 判断),不是深层次的不可变

译者注:所谓非深层次是指比如是一个对象而非一个值,其地址不变即可,内部属性可以不受限制,比如:

let a = {a:1};
let b = a;
b.b = 2;
console.log(a === b) // true

2.2. The then Method( then 方法)

A promise must provide a then method to access its current or eventual value or reason.

一个 promise 对象必须要有一个 then 方法来访问它的当前值、最终值或者据因。

A promise’s then method accepts two arguments:

promisethen 方法可以接受两个参数:

promise.then(onFulfilled, onRejected)

2.2.1. Both onFulfilled and onRejected are optional arguments:

2.2.1. onFulfilledonRejected 都是可选的参数:

 2.2.1.1. If onFulfilled is not a function, it must be ignored.

 2.2.1.1. 如果 onFulfilled 不是一个函数, 它必须被忽略。

 2.2.1.2. If onRejected is not a function, it must be ignored.

 2.2.1.2. 如果 onRejected 不是一个函数, 它必须被忽略。

2.2.2. If onFulfilled is a function:

如果 onFulfilled 是一个函数:

 2.2.2.1. it must be called after promise is fulfilled, with promise’s value as its first argument.

 2.2.2.1. 它必须在 promise 变为 fulfilled 状态后调用,且以 promise 的值(value) 作为第一个参数。

 2.2.2.2. it must not be called before promise is fulfilled.

 2.2.2.2. 它绝对不能在 promise 变为 fulfilled 状态之前被调用。

 2.2.2.3. it must not be called more than once.

 2.2.2.3. 它至多只能被调用一次。

2.2.3. If onRejected is a function,

如果 onRejected 是一个函数

 2.2.3.1. it must be called after promise is rejected, with promise’s reason as its first argument.

 2.2.3.1. 它必须在 promise 变为 rejected 状态后调用,且以 promise 的 拒因(reason)作为第一个参数

 2.2.3.2. it must not be called before promise is rejected.

 2.2.3.2. 它绝对不能在 promise 变为 rejected 状态之前被调用。

 2.2.3.3. it must not be called more than once.

 2.2.3.3. 它至多只能被调用一次。

2.2.4. onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].

onFulfilled 或者 onRejected 必须在上下文执行队列只包含平台代码时才被调用。

译者注:onFulfilled 或者 onRejected都是作为微任务,在任务队列中不存在同步逻辑任务时才会被调用

2.2.5. onFulfilled and onRejected must be called as functions (i.e. with no this value). [3.2]

2.2.5. onFulfilledonRejected 必须作为函数直接调用(也就是不使用 this 调用)。

2.2.6. then may be called multiple times on the same promise.

2.2.6. then 可能被同一个 promise 对象调用多次。

 2.2.6.1. If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.

 2.2.6.1. 如果 promise 处于 fulfilled 状态,所有从then收到的 onFulfilled 回调函数必须按顺序被调用。

 2.2.6.2. If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.

 2.2.6.2. 如果 promise 处于 rejected 状态,所有从then收到的 onRejected 回调函数必须按顺序被调用。

2.2.7. then must return a promise [3.3].

2.2.7. then 必须返回一个 promise 对象。

 promise2 = promise1.then(onFulfilled, onRejected);

 2.2.7.1. If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).

 2.2.7.1. 如果 onFulfilled 或者 onRejected 返回一个 x 值,则执行下面的Promise处理过程

 2.2.7.2. If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.

 2.2.7.2. 如果 onFulfilled 或者 onRejected 抛出一个异常 epromise2 必须拒绝执行并将 e 作为拒因。

 2.2.7.3. If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.

 2.2.7.3. 如果onFulfilled 不是函数,且 promise1 成功执行返回一个值,promise2 也必将成功执行且返回和 promise1 成功返回的相同的值

 2.2.7.4. If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.

 2.2.7.4. 如果onRejected 不是函数,且 promise1 拒绝执行,promise2 也必将拒绝执行且返回和 promise1 相同的拒因

2.3. The Promise Resolution Procedure(Promise处理过程)

The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as [[Resolve]](promise, x). If x is a thenable, it attempts to make promise adopt the state of x, under the assumption that x behaves at least somewhat like a promise. Otherwise, it fulfills promise with the value x.

promise的处理过程是一个抽象操作,将一个promisevalue 作为输入,我们可以视为[[Resolve]](promise, x)。如果 x 是一个"thenable"(可以调用 then 方法的对象),其使用方式像一个 promise 对象,则将尝试将 x 的状态赋给 promise ,否则将以 x 的值来执行 promise

This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant then method. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonable then methods.

对"thenables"的处理方式允许promise来进行交互操作,只要它们暴露出符合Promises/A+规范的then方法,这也使得符合Promises/A+规范的实现与不太符合规范的then实现有一定兼容性。

To run [[Resolve]](promise, x), perform the following steps:

[[Resolve]](promise, x) 按以下步骤运行:

2.3.1. If promise and x refer to the same object, reject promise with a TypeError as the reason.

2.3.1. 如果 promisex 指向同一个对象,promise 将拒绝执行且抛出一个 TypeError 作为拒因。

2.3.2. If x is a promise, adopt its state [3.4]:

2.3.2. 如果 x 是一个 promise 对象。接收它的状态:

 2.3.2.1. If x is pending, promise must remain pending until x is fulfilled or rejected.

 2.3.2.1. 如果 x 处于 pending 状态,则必须保留其 pending 状态至 x 变为fulfilled 或者 rejected。

 2.3.2.2. If/when x is fulfilled, fulfill promise with the same value.

 2.3.2.2. 如果 x 是 fulfilled 状态,则以 x 的值;来执行 promise

 2.3.2.3. If/when x is rejected, reject promise with the same reason.

 2.3.2.3. 如果 x 是 rejected 状态,则以 x 的拒因来拒绝执行 promise

2.3.3. Otherwise, if x is an object or function,

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

 2.3.3.1. Let then be x.then. [3.5]

 2.3.3.1. 定义一个 then 变量将 x.then 赋值给变量 then

 2.3.3.2. If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.

 2.3.3.2. 如果 x.then 取值时抛出异常 e,则拒绝执行 promise 并以 e 作为拒因。

 2.3.3.3. If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise, where:

 2.3.3.3. 如果 then 是一个函数,用 x 代替 this来调用它,resolvePromise 作为第一个参数, rejectPromise 作为第二个参数。

  2.3.3.3.1. If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).

  2.3.3.3.1. 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)

  2.3.3.3.2. If/when rejectPromise is called with a reason r, reject promise with r.

如果 rejectPromise 以拒因 r 为参数被调用,则以 r 为拒因拒绝执行 promise

  2.3.3.3.3. If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.

  2.3.3.3.3. 如果 resolvePromiserejectPromise 都被调用,或者以相同的参数被调用多次,则只执行第一次调用,其他调用被忽略。

  2.3.3.3.4. If calling then throws an exception e,

  2.3.3.3.4. 如果调动 then 方法抛出异常 e

   2.3.3.3.4.1. If resolvePromise or rejectPromise have been called, ignore it.

   2.3.3.3.4.1. 忽略 resolvePromise或者 rejectPromise 的调用。

   2.3.3.3.4.2. Otherwise, reject promise with e as the reason.

   2.3.3.3.4.2. 除此之外,拒绝执行 promise 并以 e 作为拒因

  2.3.3.4. If then is not a function, fulfill promise with x.

  2.3.3.4. 如果 then 不是一个函数,则以 x 为值执行 promise

 2.3.4. If x is not an object or function, fulfill promise with x.

 2.3.4. 如果 x 不是一个对象或者函数,,则以 x 为值执行 promise

If a promise is resolved with a thenable that participates in a circular thenable chain, such that the recursive nature of [[Resolve]](promise, thenable) eventually causes [[Resolve]](promise, thenable) to be called again, following the above algorithm will lead to infinite recursion. Implementations are encouraged, but not required, to detect such recursion and reject promise with an informative TypeError as the reason. [3.6]

如果一个 promise 在一个循环的 thenable 链中被执行,例如递归性执行 [[Resolve]](promise, thenable) 又使得其被再次调用,根据上述的算法将会陷入无限递归之中。算法虽不强制要求,但也鼓励施者检测这样的递归是否存在,若检测到存在则以一个可识别的 TypeError 为据因来拒绝 promise

3. Notes(注释)

3.1. Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfille and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.

3.1. 这里"平台代码"是指引擎、执行环境、和 promise 执行代码。在实践中,这个这个约束条件保证 onFulfilleonRejected 是异步执行的,且是在 then 被调用的 event loop 执行队列之后新的执行队列中执行。这个可以借助于 macro-task 宏任务就像:setTimeout 或者 setImmediate,或者 micro-task 微任务就像 MutationObserver 或者 process.nextTick。由于 promise 的执行被认为是平台代码,它自身在处理在处理程序时可能已经包含一个任务调度队列。

3.2. That is, in strict mode this will be undefined inside of them; in sloppy mode, it will be the global object.

3.2. this 在严格模式下将是 undefined,在非严格模式下,将是全局对象。

3.3. Implementations may allow promise2 === promise1, provided the implementation meets all requirements. Each implementation should document whether it can produce promise2 === promise1 and under what conditions.

3.3. 代码实现在满足所有要求的情况下可以允许 promise2 === promise1 。每个实现都要文档说明其是否允许以及在何种条件下允许 promise2 === promise1

3.4. Generally, it will only be known that x is a true promise if it comes from the current implementation. This clause allows the use of implementation-specific means to adopt the state of known-conformant promises.

3.4. 事实上 x 是否来自于正确的实现才决定其是否为一个正确的 promise。这一规则允许那些特例实现接受符合已知要求的 promises 状态。

3.5. This procedure of first storing a reference to x.then, then testing that reference, and then calling that reference, avoids multiple accesses to the x.then property. Such precautions are important for ensuring consistency in the face of an accessor property, whose value could change between retrievals.

3.5. 这步我们先是存储了一个指向 x.then 的引用,然后测试并调用该引用,以避免多次访问 x.then 属性。这种预防措施确保了该属性的一致性,因为其值可能在检索调用时被改变。

3.6. Implementations should not set arbitrary limits on the depth of thenable chains, and assume that beyond that arbitrary limit the recursion will be infinite. Only true cycles should lead to a TypeError; if an infinite chain of distinct thenables is encountered, recursing forever is the correct behavior.

实现方案不应该对 then 调用链的深度做限制,并且认为超出设置限制继续递归调用就是无限循环。只有当真正的环形调用才会导致 TypeError;如果明确的截然不同的 then 调用链,那么无限执行下去是正确的。

下一篇:你该知道的promise(2):实现一个promise