原文地址:https://promisesaplus.com
大乐注: 为了使译文简明清晰并更好的表意,原文中的部分术语,译文中并未强行进行翻译
An open standard for sound, interoperable JavaScript promises—by implementers, for implementers.
本文是关于 JavaScript Promise 的一个稳定,可互通(interoperable)的开放标准 — 由开发者制定, 为开发者服务
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.
pormise 表示一个异步操作的最终结果。then 方法是与一个 promise交互的主要方法,该方法通过注册回调函数的形式来接收promise的value或其无法被fulfill的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 提案的行为准则,扩展其内容以覆盖一些事实上的行为,并去除了其表意不清或有问题的一些部分
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一个promise给出明确规范,而是选择专注于提供一个可互通的then方法。在未来关于配套规范的工作中我们可能会涉及这些主题。
1. Terminology - 术语
- “promise” is an object or function with a then method whose behavior conforms to this specification.
- “thenable” is an object or function that defines a then method.
- “value” is any legal JavaScript value (including undefined, a thenable, or a promise).
- “exception” is a value that is thrown using the throw statement.
- “reason” is a value that indicates why a promise was rejected.
- “
promise” 指带有then方法的,且行为符合本规范的描述的object或fucntion。 - “
thenable” 指定义了一个then方法的object或fucntion。 - “
value” 指任何合法的JavaScript值(包括undefined,以及前面提到的thenable和promise)。(大乐注:这里的value不是JS语言中值的概念,而是表示promise本身的“值”,为明确表意,后续译文中表示 promise的“值”均使用value) - “
exception” 指通过throw语句来抛出的一个值 - “
reason” 指用于表明一个promise被reject的原因的一个值
2. Requirements - 要求
2.1 Promise States - Promise的状态
A promise must be in one of three states: pending, fulfilled, or rejected.
- 2.1.1 When pending, a promise:
- 2.1.1.1 may transition to either the fulfilled or rejected state.
- 2.1.2 When fulfilled, a promise:
- 2.1.2.1 must not transition to any other state.
- 2.1.2.2 must have a value, which must not change.
- 2.1.3 When rejected, a promise:
- 2.1.3.1 must not transition to any other state.
- 2.1.3.2 must have a reason, which must not change. Here, “must not change” means immutable identity (i.e.
===), but does not imply deep immutability.
一个promise必须处于以下三个状态之一:pending,fulfilled或者rejected。
- 2.1.1 当一个
promise处于pending状态时:- 2.1.1.1 只能转换到
fulfilled或rejected二个状态之一。
- 2.1.1.1 只能转换到
- 2.1.2 当一个
promise处于fulfilled状态时:- 2.1.2.1 不能再转换到任何其它状态。
- 2.1.2.2 必须有一个
value,且其值不能改变。
- 2.1.3 当一个
promise处于rejected状态时:- 2.1.3.1 不能再转换到其它任何状态。
- 2.1.3.2 必须有一个
reason,且其值不能改变。 这里,“不能改变”是指其引用不可变 (i.e. ===), 但不要求深层的不变.
2.2 The then Method - then方法
*A promise must provide a
thenmethod to access its current or eventual value or reason.A promise’s
thenmethod accepts two arguments:*promise.then(onFulfilled, onRejected)
promise必须提供一个then方法来获取其当前或最终的value或reason
pormise的then方法接收两个参数:
promise.then(onFulfilled, onRejected)
- 2.2.1 Both
onFulfilledandonRejectedare optional arguments:
- 2.2.1.1 If
onFulfilledis not a function, it must be ignored.- 2.2.1.2 If
onRejectedis not a function, it must be ignored.
- 2.2.1
onFulfilled和onRejected都是可选参数:- 2.2.1.1 如果
onFulfilled不是一个函数,它必须被忽略。 - 2.2.1.2 如果
onRejected不是一个函数,它必须被忽略。
- 2.2.1.1 如果
- 2.2.2 If
onFulfilledis a function:
- 2.2.2.1 it must be called after
promiseis fulfilled, withpromise’s value as its first argument.- 2.2.2.2 it must not be called before
promiseis fulfilled.- 2.2.2.3 it must not be called more than once.
- 2.2.2 如果
onFulfilled是一个函数:- 2.2.2.1 它必须在
promise被fulfill后调用,promise的value是它的第一个参数。 - 2.2.2.2 它不能在
promise被fulfill前调用。 - 2.2.2.2 它不能被调用超过一次。
- 2.2.2.1 它必须在
- 2.2.3 If
onRejectedis a function:
- 2.2.3.1 it must be called after
promiseis rejected, withpromise’s reason as its first argument.- 2.2.3.2 it must not be called before
promiseis rejected.- 2.2.3.3 it must not be called more than once.
- 2.2.3 如果
onRejected是一个函数:- 2.2.3.1 它必须在
promise被rejected后调用,promise的reason是它的第一个参数。 - 2.2.3.2 它不能在
promise被rejected前调用。 - 2.2.3.2 它不能被调用超过一次。
- 2.2.3.1 它必须在
- 2.2.4
onFulfilledoronRejectedmust not be called until the execution context stack contains only platform code. [3.1].
- 2.2.4
onFulfilled或者onRejected在execution context仅包含平台代码之前不得被调用。[3.1]
- 2.2.5 onFulfilled and onRejected must be called as functions (i.e. with no this value). [3.2]
- 2.2.5
onFulfilled和onRejected只能被作为函数调用(例如:没有this)。[3.2]
- 2.2.6
thenmay be called multiple times on the same 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.2 If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.
- 2.2.6 同一
promise的then可以被调用多次。- 2.2.6.1 如果/当
promise处于fulfilled状态,所有响应的onFulfilled回调必须按它们最初调用then的顺序执行 - 2.2.6.2 如果/当
promise处于rejected状态,所有响应的onRejected回调必须按它们最初调用then的顺序执行
- 2.2.6.1 如果/当
- 2.2.7 then must return a promise [3.3].
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.2 If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.
- 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.4 If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.
- 2.2.7
then必须返回一个promise[3.3]。// 大乐注:我们假设有以下上下文 promise2 = promise1.then(onFulfilled, onRejected);- 2.2.7.1 如果(
promise1的)onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x) - 2.2.7.2 如果(
promise1的)onFulfilled或onRejected之一抛出一个异常e,promise2必须以e作为reason被reject - 2.2.7.3 如果(
promise1的)onFulfilled不是一个函数且promise1变为fulfilled状态,promise2必须以和promise1相同的value被fulfill(大乐注:promise1的onFulfilled被忽略了) - 2.2.7.4 如果(
promise1的)onRejected不是一个函数且promise1变为rejected状态,promise2必须以和promise1相同的reason被reject(大乐注:promise1的onRejected被忽略了)
- 2.2.7.1 如果(
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解析流程指接收一个promise和一个任意值x作为输入的一个抽象流程,表示为[[Resolve]](promise, x)。如果x为thenable,它会尝试让promise继承x的状态,前提是x至少行为与promise有一定的相似。否则,它将以x作为value来fulfill这个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.
To run
[[Resolve]](promise, x), perform the following steps:
这种处理thenable的方式允许promise的不同实现互通,只要他们都暴露一个符合Promises/A+规范的then方法。它同时也能支持基于Promises/A+规范的实现与其它不规范但合理的实现(至少带有一个then方法)在一定程度上互相兼容
[[Resolve]](promise, x)按以下步骤执行:
- 2.3.1 If
promiseandxrefer to the same object, rejectpromisewith aTypeErroras the reason.
- 2.3.1 如果
promise和x引用同一个对象,以TypeError作为reason来reject这个promise
- 2.3.2 If
xis a promise, adopt its state [3.4]:
- 2.3.2.1 If
xis pending,promisemust remain pending untilxis fulfilled or rejected.- 2.3.2.2 If/when
xis fulfilled, fulfillpromisewith the same value.- 2.3.2.3 If/when
xis rejected, rejectpromisewith the same reason.
- 2.3.2 如果
x是一个promise,接受它的状态[3.4]:- 2.3.2.1 如果
x处于pending状态,直到x变为fulfilled或rejected状态,promise必须保持pending状态。 - 2.3.2.2 如果/当
x变为fulfilled状态,以相同的value来fulfillpromise - 2.3.2.2 如果/当
x变为rejected状态,以相同的reason来rejectpromise
- 2.3.2.1 如果
- 2.3.3 Otherwise, if
xis an object or function:
- 2.3.3.1 Let
thenbex.then. [3.5]- 2.3.3.2 If retrieving the property
x.thenresults in a thrown exceptione, rejectpromisewitheas the reason.- 2.3.3.3 If
thenis a function, call it withxasthis, first argumentresolvePromise, and second argumentrejectPromise, where:
- 2.3.3.3.1 If/when
resolvePromiseis called with a valuey, run[[Resolve]](promise, y).- 2.3.3.3.2 If/when
rejectPromiseis called with a reasonr, rejectpromisewithr.- 2.3.3.3.3 If both
resolvePromiseandrejectPromiseare 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.4 If calling
thenthrows an exceptione:
- 2.3.3.3.4.1 If
resolvePromiseorrejectPromisehave been called, ignore it.- 2.3.3.3.4.2 Otherwise, reject
promisewitheas the reason.- 2.3.3.4 If
thenis not a function, fulfillpromisewithx.
- 2.3.3 反之, 如果
x是一个object或function:- 2.3.3.1 把
then设置成x.then。[3.5] - 2.3.3.2 如果访问
x.then属性导致抛出了一个异常(设为e),以e作为reason来rejectpromise。 - 2.3.3.3 如果
then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromise- 2.3.3.3.1 如果/当
resolvePromise以y作为value被调用, 执行[[Resolve]](promise, y). - 2.3.3.3.2 如果/当
rejectPromise以r作为reason被调用, 以r为reason来rejectpromise. - 2.3.3.3.3 如果
resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用。 - 2.3.3.3.4 如果调用
then抛出一个异常e:- 2.3.3.3.4.1 如果
resolvePromise已被调用过rejectPromise,忽略异常。 - 2.3.3.3.4.2 否则,以
e作为reason来rejectpromise。
- 2.3.3.3.4.1 如果
- 2.3.3.3.1 如果/当
- 2.3.3.4 如果
then不是一个函数,以x作为value来fulfillpromise。
- 2.3.3.1 把
- 2.3.4 If
xis not an object or function, fulfillpromisewithx.
- 2.3.4 如果
x不是object或function,将x作为value来fulfillpromise。
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 rejectpromisewith an informativeTypeErroras the reason. [3.6]
如果一个promise以一个会导致链式循环的thenable被解析,比如从[[Resolve]](promise, thenable)开始执行最终导致[[Resolve]](promise, thenable)再次被执行,遵从以上算法会导致无限递归。我们鼓励,但不强求实现(此规范)时检测这种递归并以一个告知性的TypeError作为reason来reject这个promise。[3.6]
3. Notes - 注释
3.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.
3.1 这里的“平台代码”意味着引擎,环境和promise实现代码。实践中要确保 onFulfilled和onRejected方法是异步执行的,且应该在then方法被调用的那一轮事件循环之后的新执行栈中执行。可以按“宏任务”实现(例如setTimeout或setImmediate),也者按“微任务”实现(例如MutationObserver或process.nextTick)。由于promise实现被认为是平台代码,故代码自身在处理在处理程序时可能已经包含一个任务调度队列。
(大乐注:这里需要了解有关宏任务与微任务的概念 -- 简而言之:在本轮事件循环运行完成之前,回调函数不会被调用。)
3.2 That is, in strict mode
thiswill beundefinedinside of them; in sloppy mode, it will be the global object.
3.2 也就是说,在严格模式中,函数内this的值为undefined;在非严格模式中this为全局对象。
3.3 Implementations may allow
promise2 === promise1, provided the implementation meets all requirements. Each implementation should document whether it can producepromise2 === promise1and under what conditions.
3.3 (此规范的)实现可以允许promise2 === promise1,只要其符满足规范内的所有要求。但每一个实现应当在文档中阐明它是否(且在何种情况下)会产生promise2 === promise1这一情况。
3.4 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.
3.4 通常,只有x和promise为同一实现时,我们才能知道此条件为真。此条规则允许每个实现使用自己特有的方式来接受已知符合要求的promise(大乐注:指x)的状态
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属性。这种预防措施对于保证一致性十分重要,因为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.
3.6 (此规范的)实现不应当对thenable链的深度故意做出限制并假设超过这一限制值得递归是无限循环。只有真正的循环才应当导致抛出TypeError;如果出现一条由彼此唯一的theable组成的无限的链,那么一直无限递归下去是正确的行为。