An open standard for sound, interoperable JavaScript promises—by implementers, for implementers.
一个开放、健全且通用的 JavaScript Promise 标准。由开发者制定,供开发者参考。
A 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 术语
-
promise” is an object or function with a
thenmethod whose behavior conforms to this specification.
"prmoise" 是一个拥有符合本规范的 then 方法的对象或者函数。 -
“thenable” is an object or function that defines a
thenmethod. "thenable" 是一个定义了then方法的对象或者函数。 -
“value” is any legal JavaScript value (including
undefined, a thenable, or a promise).
"value" 是 JavaScript 的任意合法值(包括undefined, thenable, promise)。 -
“exception” is a value that is thrown using the
throwstatement.
"exception" 是一个用 throw 语句抛出的 value 。 -
“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.
- When pending, a promise: 当 promise 处于 pending 状态时:
- may transition to either the fulfilled or rejected state.可以转换到 fulfilled 或 rejected 状态。
- When fulfilled, a promise:当 promise 处于 fulfilled 状态时:
- must not transition to any other state.不能转换到其他状态
- must have a value, which must not change.必须有一个 value ,并且不能改变。
- When rejected, a promise:当 promise 处于 rejected 状态时:
- must not transition to any other state.不能转换到其他状态
- 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)
- Both
onFulfilledandonRejectedare optional arguments:onFulfilled和onRejected都是可选参数:- If
onFulfilledis not a function, it must be ignored.如果onFulfilled不是函数,则忽略。 - If
onRejectedis not a function, it must be ignored. 如果onRejected不是函数,则忽略。
- If
- If
onFulfilledis a function:如果onFulfilled是一个函数:- it must be called after promise is fulfilled, with promise’s value as its first argument.它必须在
promise被fulfilled后,以promise的value作为第一个参数调用。 - it must not be called before promise is fulfilled.它不能在
promise被fulfilled之前调用。 - it must not be called more than once.它不能被调用多次。
- it must be called after promise is fulfilled, with promise’s value as its first argument.它必须在
- If
onRejectedis a function:如果onRejected是一个函数:- it must be called after
promiseis rejected, withpromise’s reason as its first argument.它必须在promise被rejected后,以promise的reason作为第一个参数调用。 - it must not be called before
promiseis rejected.它不能能在promise被rejected之前调用。 - it must not be called more than once..它不能被调用多次。
- it must be called after
onFulfilledoronRejectedmust not be called until the execution context stack contains only platform code.在 execution context 栈(执行上下文栈)只包含平台代码之前,onFulfilled或者onRejected不能被调用 [3.1].onFulfilledandonRejectedmust be called as functions (i.e. with nothisvalue).onFulfilled或者onRejected必须以函数形式调用(即不能有this值)[3.2]thenmay be called multiple times on the same promise.then方法可以被同一个promise调用多次。- If/when
promiseis fulfilled, all respectiveonFulfilledcallbacks must execute in the order of their originating calls tothen.如果或者当promise处于fulfilled状态, 所有自己的onFulfilled回调函数,必须要按照then注册的顺序被调用。 - If/when
promiseis rejected, all respectiveonRejectedcallbacks must execute in the order of their originating calls tothen如果或者当promise处于rejected状态, 所有自己的onRejected回调函数,必须要按照then注册的顺序被调用。
- If/when
thenmust return a promise.then方法必须要返回promise[3.3].promise2 = promise1.then(onFulfilled, onRejected);- If either
onFulfilledoronRejectedreturns a valuex, run the Promise Resolution Procedure[[Resolve]](promise2, x).如果onFulfilled或者onRejected返回一个值x,则执行 Promise Resolution Procedure[[Resolve]](promise2, x). - If either
onFulfilledoronRejectedthrows an exceptione,promise2must be rejected witheas the reason.如果onFulfilled或者onRejected抛出异常e,promise2必须以e作为 reason ,转到 rejected 状态。 - If
onFulfilledis not a function andpromise1is fulfilled,promise2must be fulfilled with the same value aspromise1.如果onFulfilled不是函数,并且promise1处于 fulfilled 状态 ,则promise2必须以与promise1同样的 value 被 fulfilled . - If
onRejectedis not a function andpromise1is rejected,promise2must be rejected with the same reason aspromise1.如果onRejected不是函数,并且promise1处于 rejected 状态 ,则promise2必须以与promise1同样的 reason 被 rejected .
- If either
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) 执行以下步骤:
- If
promiseandxrefer to the same object, rejectpromisewith aTypeErroras the reason.如果promise和x引用的是同一个对象,则以一个TypeError作为 reason 让promise转为 rejected 状态。 - If
xis a promise, adopt its state 如果x也是一个 promise ,则让promise接受它的状态[3.4]: 1. Ifxis pending,promisemust remain pending untilxis fulfilled or rejected.如果x处于 pending 状态,promise必须保持 pending 状态,直到x变成 fulfilled 或者 rejected 状态,promise才同步改变。 2. If/whenxis fulfilled, fulfillpromisewith the same value.如果或者当x处于 fulfilled 状态, 以同样的 value 让promise也变成 fulfilled 状态。 3. If/whenxis rejected, rejectpromisewith the same reason.如果或者当x处于 rejected 状态, 以同样的 reason 让promise也变成 rejected 状态。 - Otherwise, if
xis an object or function,如果x是一个对象或者函数- Let
thenbex.then.令then等于x.then. [3.5] - If retrieving the property
x.thenresults in a thrown exceptione, rejectpromisewitheas the reason.如果读取x.then抛出异常e, 以e作为 reason 让promise变成 rejected 状态。 - If
thenis a function, call it withxasthis, first argumentresolvePromise, and second argumentrejectPromise, where:如果then是一个函数,以x作为this调用它,传入第一个参数resolvePromise, 第二个参数rejectPromise。- If/when
resolvePromiseis called with a valuey, run[[Resolve]](promise, y). 如果resolvePromise被传入y调用, 则执行[[Resolve]](promise, y) - If/when
rejectPromiseis called with a reasonr, rejectpromisewithr. 如果rejectedPromise被传入r调用,则用,r作为 reason 让promise变成 rejected 状态 - If both
resolvePromiseandrejectPromiseare called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.如果resolvePromise和rejectPromise都被调用了,或者被调用多次了。只有第一次调用生效,其余会被忽略。 - If calling
thenthrows an exceptione,如果调用then抛出异常e, 1. IfresolvePromiseorrejectPromisehave been called, ignore it. 如果resolvepromise或rejectPromise已经被调用过了,则忽略它。 2. Otherwise, rejectpromisewitheas the reason.否则, 以e作为 reason 让promise变成 rejected 状态。
- If/when
- If
thenis not a function, fulfillpromisewithx.如果then不是一个函数,以x作为 value 让promise变成 fulfilled 状态。
- Let
- If
xis not an object or function, fulfillpromisewithx.如果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 备注
-
Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that
onFulfilledandonRejectedexecute asynchronously, after the event loop turn in whichthenis called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such assetTimeoutorsetImmediate, or with a “micro-task” mechanism such asMutationObserverorprocess.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 的实施代码。实践中要确保onFulfilled和onRejected方法异步执行,且应该在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
- macro-task: script(整体代码),
-
That is, in strict mode
thiswill beundefinedinside of them; in sloppy mode, it will be the global object.
也就是说在**严格模式(strict)**中,函数this的值为undefined;在非严格模式中其为全局对象。 -
Implementations may allow
promise2 === promise1, provided the implementation meets all requirements. Each implementation should document whether it can producepromise2 === promise1and under what conditions. 代码实现在满足所有要求的情况下可以允许promise2 === promise1。每个实现都要文档说明其是否允许以及在何种条件下允许promise2 === promise1。 -
Generally, it will only be known that
xis 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 状态。 -
This procedure of first storing a reference to
x.then, then testing that reference, and then calling that reference, avoids multiple accesses to thex.thenproperty. Such precautions are important for ensuring consistency in the face of an accessor property, whose value could change between retrievals.
这步我们先是存储了一个指向x.then的引用,然后测试并调用该引用,以避免多次访问x.then属性。这种预防措施确保了该属性的一致性,因为其值可能在检索调用时被改变。 -
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 均不相同,那么递归下去永远是正确的行为。