Promise A+ 逐句翻译

123 阅读11分钟

An open standard for sound, interoperable JavaScript promises—by implementers, for implementers.
一个开放、健全且通用的 JavaScript Promise 标准。由开发者制定,供开发者参考。

promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled.
一个 promise 表示异步操作的最终结果。与 promise 进行交互的主要方式是通过它的方法 then。该方法通过注册回调来得到这个 promise 的最终 value ,或者为什么这个 promise 不能被 fulfilled 的 reason 。

This specification details the behavior of the then method, providing an interoperable base which all Promises/A+ conformant promise implementations can be depended on to provide. As such,the specification should be considered very stable. Although the Promises/A+ organization may occasionally revise this specification with minor backward-compatible changes to address newly-discovered corner cases, we will integrate large or backward-incompatible changes only after careful consideration, discussion, and testing.
该规范详细说明了 then 方法的行为,提供了一个可互操作的基础,因此所有符合 Promises/A+ 的 promise 实现都可以依赖该基础。尽管 Promises/A+ 组织可能偶尔会通过向后兼容的微小更改来修改此规范,以解决新发现的情况,但我们只有在仔细考虑、讨论和测试后才会进行大的或向后不兼容的更改。因此, 该规范应该被认为是十分稳定的

Historically, Promises/A+ clarifies the behavioral clauses of the earlier Promises/A proposal, extending it to cover de facto behaviors and omitting parts that are underspecified or problematic.
从历史上看, Promises/A+ 阐明了早期 Promises/A proposal 的条款,并将部分事实上已经实现的拓展涵盖其中,以及对某些未指定或者有问题的部分省略。

Finally, the core Promises/A+ specification does not deal with how to create, fulfill, or reject promises, choosing instead to focus on providing an interoperable then method. Future work in companion specifications may touch on these subjects.
最后,Promises/A+ 规范的核心不包括:如何 create 、fulfill 或 reject promises。而是选择专注于提供可互操作的 then 方法。不过伴随规范的未来工作可能会涉及这些主题

1. Terminology 术语

  1. promise” is an object or function with a then method whose behavior conforms to this specification.
    "prmoise" 是一个拥有符合本规范的 then 方法的对象或者函数。

  2. “thenable” is an object or function that defines a then method. "thenable" 是一个定义了 then 方法的对象或者函数。

  3. “value” is any legal JavaScript value (including undefined, a thenable, or a promise).
    "value" 是 JavaScript 的任意合法值(包括 undefined, thenable, promise)。

  4. “exception” is a value that is thrown using the throw statement.
    "exception" 是一个用 throw 语句抛出的 value 。

  5. “reason” is a value that indicates why a promise was rejected.
    "reason" 是一个表示 promise 被 rejected 的 value 。

2. Requirements 要求

2.1. Promise States promise 的状态

A promise must be in one of three states: pending, fulfilled, or rejected. pormise 必须是以下三个状态之一: pending, fulfilled, rejected.

  1. When pending, a promise: 当 promise 处于 pending 状态时:
    1. may transition to either the fulfilled or rejected state.可以转换到 fulfilled 或 rejected 状态。
  2. When fulfilled, a promise:当 promise 处于 fulfilled 状态时:
    1. must not transition to any other state.不能转换到其他状态
    2. must have a value, which must not change.必须有一个 value ,并且不能改变。
  3. When rejected, a promise:当 promise 处于 rejected 状态时:
    1. must not transition to any other state.不能转换到其他状态
    2. must have a reason, which must not change.必须有一个 reason ,并且不能改变。

Here, “must not change” means immutable identity (i.e. ===), but does not imply deep immutability.在这里,“不能改变”意味着严格相等(即 ===) ,但并不意味着深度不可变性(属性可变)。

2.2. The then Method then 方法

A promise must provide a then method to access its current or eventual value or reason.promise 必须提供一个 then 方法,能由此去访问当前或最终的 value 或者 reason 。

A promise’s then method accepts two arguments:promise 的 then 方法, 接受两个参数:

promise.then(onFulfilled, onRejected)
  1. Both onFulfilled and onRejected are optional arguments:onFulfilled 和 onRejected 都是可选参数:
    1. If onFulfilled is not a function, it must be ignored.如果 onFulfilled 不是函数,则忽略。
    2. If onRejected is not a function, it must be ignored. 如果 onRejected 不是函数,则忽略。
  2. If onFulfilled is a function:如果 onFulfilled 是一个函数:
    1. it must be called after promise is fulfilled, with promise’s value as its first argument.它必须在 promise 被 fulfilled 后,以 promise 的 value 作为第一个参数调用。
    2. it must not be called before promise is fulfilled.它不能在 promise 被 fulfilled 之前调用。
    3. it must not be called more than once.它不能被调用多次。
  3. If onRejected is a function:如果 onRejected 是一个函数:
    1. it must be called after promise is rejected, with promise’s reason as its first argument.它必须在 promise 被 rejected 后,以 promise 的 reason 作为第一个参数调用。
    2. it must not be called before promise is rejected.它不能能在 promise 被 rejected 之前调用。
    3. it must not be called more than once..它不能被调用多次。
  4. onFulfilled or onRejected must not be called until the execution context stack contains only platform code.在 execution context 栈(执行上下文栈)只包含平台代码之前, onFulfilled 或者 onRejected 不能被调用 [3.1].
  5. onFulfilled and onRejected must be called as functions (i.e. with no this value). onFulfilled 或者 onRejected 必须以函数形式调用(即不能有this值)[3.2]
  6. then may be called multiple times on the same promise.then 方法可以被同一个 promise 调用多次。
    1. If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.如果或者当 promise 处于 fulfilled 状态, 所有自己的 onFulfilled 回调函数,必须要按照 then 注册的顺序被调用。
    2. If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then如果或者当 promise 处于 rejected 状态, 所有自己的 onRejected 回调函数,必须要按照 then 注册的顺序被调用。
  7. then must return a promise. then 方法必须要返回 promise [3.3].
    promise2 = promise1.then(onFulfilled, onRejected);
    
    1. If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).如果 onFulfilled 或者 onRejected 返回一个值 x ,则执行 Promise Resolution Procedure [[Resolve]](promise2, x).
    2. If either onFulfilled or onRejected throws an exception epromise2 must be rejected with e as the reason.如果 onFulfilled 或者 onRejected 抛出异常 e , promise2 必须以 e 作为 reason ,转到 rejected 状态。
    3. If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.如果 onFulfilled 不是函数,并且 promise1 处于 fulfilled 状态 ,则 promise2 必须以与 promise1 同样的 value 被 fulfilled .
    4. If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.如果 onRejected 不是函数,并且 promise1 处于 rejected 状态 ,则 promise2 必须以与 promise1 同样的 reason 被 rejected .

2.3. The Promise Resolution Procedure

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 Resolution Procedure 是一个抽象操作。它以一个 promise 和一个 value 作为输入,记作:[[Resolve]](promise, x) 。 如果 x 是一个 thenable , 它会尝试让 promise 变成与 x 的一样状态 ,前提 x 是一个类似的 promise 对象。否则,它会让 promise 以 x 作为 value 转为 fulfilled 状态。

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) 执行以下步骤:

  1. If promise and x refer to the same object, reject promise with a TypeError as the reason.如果 promise 和 x 引用的是同一个对象,则以一个 TypeError 作为 reason 让 promise 转为 rejected 状态。
  2. If x is a promise, adopt its state 如果 x 也是一个 promise ,则让 promise 接受它的状态[3.4]: 1. If x is pending, promise must remain pending until x is fulfilled or rejected.如果 x 处于 pending 状态,promise 必须保持 pending 状态,直到 x 变成 fulfilled 或者 rejected 状态,promise 才同步改变。 2. If/when x is fulfilled, fulfill promise with the same value.如果或者当 x 处于 fulfilled 状态, 以同样的 value 让 promise 也变成 fulfilled 状态。 3. If/when x is rejected, reject promise with the same reason.如果或者当 x 处于 rejected 状态, 以同样的 reason 让 promise 也变成 rejected 状态。
  3. Otherwise, if x is an object or function,如果 x 是一个对象或者函数
    1. Let then be x.then.令 then 等于 x.then. [3.5]
    2. If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.如果读取 x.then 抛出异常 e , 以 e 作为 reason 让 promise 变成 rejected 状态。
    3. If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise, where:如果 then 是一个函数,以 x 作为 this 调用它,传入第一个参数 resolvePromise , 第二个参数 rejectPromise 。
      1. If/when resolvePromise is called with a value y, run [[Resolve]](promise, y). 如果 resolvePromise 被传入 y 调用, 则执行 [[Resolve]](promise, y)
      2. If/when rejectPromise is called with a reason r, reject promise with r. 如果 rejectedPromise 被传入 r 调用,则用,r 作为 reason 让 promise 变成 rejected 状态
      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.如果 resolvePromise 和 rejectPromise 都被调用了,或者被调用多次了。只有第一次调用生效,其余会被忽略。
      4. If calling then throws an exception e,如果调用 then 抛出异常 e , 1. If resolvePromise or rejectPromise have been called, ignore it. 如果 resolvepromise 或 rejectPromise 已经被调用过了,则忽略它。 2. Otherwise, reject promise with e as the reason.否则, 以 e 作为 reason 让 promise 变成 rejected 状态。
    4. If then is not a function, fulfill promise with x.如果 then 不是一个函数,以 x 作为 value 让 promise 变成 fulfilled 状态。
  4. If x is not an object or function, fulfill promise with x.如果 x 不是对象或函数, 以 x 作为 value 让 promise 变成 fulfilled 状态。

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 链中的对象 resolved,而 [[Resolve]](promise, thenable) 的递归性质又使得其被再次调用,根据上述的算法将会陷入无限递归之中。算法虽不强制要求,但也鼓励实现者检测这样的递归是否存在,并且以 TypeError 作为 reason 拒绝 promise[3.6] 。

3. Notes 备注

  1. Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled 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. 这里的平台代码指的是引擎、环境以及 promise 的实施代码。实践中要确保 onFulfilledonRejected 方法异步执行,且应该在 then 方法被调用的那一轮事件循环之后的新执行栈中执行。这个事件队列可以采用“宏任务(macro-task)”机制或者“微任务(micro-task)”机制来实现。由于 promise 的实施代码本身就是平台代码(**译者注:**即都是 JavaScript),故代码自身在处理在处理程序时可能已经包含一个任务调度队列。

    两个类别的具体分类如下:

    • macro-task: script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
    • micro-task: process.nextTick, Promises(这里指浏览器实现的原生 Promise), Object.observe, MutationObserver
  2. That is, in strict mode this will be undefined inside of them; in sloppy mode, it will be the global object.
    也就是说在**严格模式(strict)**中,函数 this 的值为 undefined ;在非严格模式中其为全局对象。

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

  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.
    总体来说,如果 x 符合当前实现,我们才认为它是真正的 promise 。这一规则允许那些特例实现接受符合已知要求的 Promises 状态。

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

  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. 实现不应该对 thenable 链的深度设限,并假定超出本限制的递归就是无限循环。只有真正的循环递归才应能导致 TypeError 异常;如果一条无限长的链上 thenable 均不相同,那么递归下去永远是正确的行为。