Promise概念(规范地址:promisesaplus.com/)
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方法, then方法注册回调用于接收Priomse的结果,不管这个结果是最终的值,还是无法实现Promise的原因。
Terminology 术语
“promise” is an object or function with a
thenmethod whose behavior conforms to this specification.
- Promise是具有then方法的对象或者函数,它的行为要符合Promiseg规范
“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 语句抛出的异常值。
“reason” is a value that indicates why a promise was rejected.
-
“reason” 是一个值,表示承诺被拒绝的原因
Requirements 要求
Promise States Promise状态
A promise must be in one of three states: pending, fulfilled, or rejected.
- Promise 必须处于以下三种状态之一:pending、fulfilled或rejected。
When pending, a promise: may transition to either the fulfilled or rejected state.
- 当Promise 处于pending状态时,可以转换到fulfilled或者rejected
When fulfilled, a promise:
- must not transition to any other state. 2. must have a value, which must not change.
- 当Promise 处于fulfilled状态时: 不得转换到任何其他状态; 必须有一个不能改变的值。
When rejected, a promise:
- must not transition to any other state. 2. must have a reason, which must not change.
- 当Promise 处于rejected状态时: 不得转换到任何其他状态; 必须有一个不能改变的原因。
The then Method then方法
A promise must provide a
thenmethod to access its current or eventual value or reason.
- Promise 必须提供 then 方法来访问其当前或者最终值,或者没有实现的原因
A promise’s
thenmethod accepts two arguments:
-
一个 Promise 的 then 方法接受两个参数:
promise.then(onFulfilled, onRejected)
Both
onFulfilledandonRejectedare optional arguments: 1. IfonFulfilledis not a function, it must be ignored. 2. IfonRejectedis not a function, it must be ignored.
- onFulfilled 和 onRejected 都是可选参数:
- 如果 onFulfilled 不是函数,则必须忽略它;
- 如果 onRejected 不是函数,则必须忽略它;
If
onFulfilledis a function 1. it must be called afterpromiseis fulfilled, withpromise’s value as its first argument.
2. it must not be called beforepromiseis fulfilled. 3. it must not be called more than once.
- 如果 onFulfilled 是一个函数:
- 必须在 Promise 完成后调用它,Promise 的值作为它的第一个参数;
- 在 Promise 完成之前不能调用它;
- 它不能被多次调用;
If
onRejectedis a function 1. it must be called afterpromiseis rejected, withpromise’s reason as its first argument.
2. it must not be called beforepromiseis rejected. 3. it must not be called more than once.
- 如果 onRejected 是一个函数:
- 必须在 Promise 被拒绝后调用它,Promise 的原因作为它的第一个参数;
- 在 Promise 完成之前不能调用它;
- 它不能被多次调用;
onFulfilledoronRejectedmust not be called until the execution context stack contains only platform code.
- 在执行上下文堆栈仅包含平台代码之前,不得调用 onFulfilled 或 onRejected
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.
- 这里的“platform code”是指引擎、环境和Promise实现代码。在实践中,这个要求确保 onFulfilled 和 onRejected 异步执行,在调用 then 的事件循环之后,并使用新的堆栈。这可以通过“宏任务”机制(例如 setTimeout 或 setImmediate)或“微任务”机制(例如 MutationObserver 或 process.nextTick)来实现。由于Promise实现被认为是平台代码,在操作者调用时,它本身可能包含一个任务调度队列或“trampoline”。
onFulfilledandonRejectedmust be called as functions (i.e. with nothisvalue).
- onFulfilled 和 onRejected 必须作为函数调用(即没有 this 值)
thisvalue
That is, in strict mode this will be undefined inside of them; in sloppy mode, it will be the global object.
- 在严格模式下,这在它们内部是未定义的;在非严格模式下,它将是全局对象。
thenmay be called multiple times on the same promise.
1. If/whenpromiseis fulfilled, all respectiveonFulfilledcallbacks must execute in the order of their originating calls tothen.
2. If/whenpromiseis rejected, all respectiveonRejectedcallbacks must execute in the order of their originating calls tothen.
- then 可以在同一个 promise 上多次调用。
- 如果/当Promise被实现,所有相应的 onFulfilled 回调必须按照它们对 then 的原始调用的顺序执行。
- 如果/当Promise被拒绝时,所有相应的 onRejected 回调必须按照它们对 then 的原始调用的顺序执行。
thenmust return a promisepromise2 = promise1.then(onFulfilled, onRejected);1. If either
onFulfilledoronRejectedreturns a valuex, run the Promise Resolution Procedure[[Resolve]](promise2, x).
2. If eitheronFulfilledoronRejectedthrows an exceptione,promise2must be rejected witheas the reason
3. If
onFulfilledis not a function andpromise1is fulfilled,promise2must be fulfilled with the same value aspromise1.4. If
onRejectedis not a function andpromise1is rejected,promise2must be rejected with the same reason aspromise1.
- then 方法必须返回一个Promise。
- 如果 onFulfilled 或 onRejected 返回值 x,则运行 Promise Resolution Procedure [[Resolve]](promise2, x)。
- 如果 onFulfilled 或 onRejected 抛出异常 e,promise2 必须以 e 作为原因被拒绝。
- 如果 onFulfilled 不是函数并且 promise1 已实现,则 promise2 必须以与 promise1 相同的值实现。
- 如果 onRejected 不是函数并且 promise1 被拒绝,则 promise2 必须以与 promise1 相同的原因被拒绝。
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 以及在什么条件下。
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和value作为输入,我们将其表示为 [[Resolve]](promise, x)。如果 x 是一个 thenable,它会尝试让 Promise 采用 x 的状态,假设 x 的行为至少有点像 Promise。否则,它以值 x 履行承诺。
This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant
thenmethod. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonablethenmethods.
- 对 thenables 的这种处理允许 promise 实现互操作,只要它们公开一个符合 Promises/A+ 的 then 方法。它还允许 Promises/A+ 实现用合理的 then 方法“assimilate”不一致的实现。
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 作为原因拒绝 promise
If
xis a promise, adopt its state:
1. Ifxis pending,promisemust remain pending untilxis fulfilled or rejected.
2. If/whenxis fulfilled, fulfillpromisewith the same value.
3. If/whenxis rejected, rejectpromisewith the same reason.
- 如果 x 是一个Promise,采用它的状态
- 如果 x 是pending,Promise 必须保持pending直到 x 被实现或拒绝。
- 如果/当 x 完成时,用相同的值实现Promise。
- 如果/当 x 被拒绝时,以同样的理由拒绝Promise。
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 来自当前的实现时,才会知道 x 是一个真正的承诺。该条款允许使用特定实现的手段来采用已知符合Promise的状态。
Otherwise, if
xis an object or function
- 否则,如果 x 是一个对象或函数
如果检索属性 x.then 导致抛出异常 e,则以 e 为原因拒绝 promise。 如果 then 是一个函数,则使用 x 作为 this 调用它,第一个参数是 resolvePromise,第二个参数是 rejectPromise,其中: 如果/当使用值 y 调用 resolvePromise 时,运行 [[Resolve]](promise, y)。
Let
thenbex.then.
- 设 then 为 x.then
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 属性的多次访问。这些预防措施对于确保访问器属性的一致性很重要,访问器属性的值可能会在检索之间发生变化。
If retrieving the property
x.thenresults in a thrown exceptione, rejectpromisewitheas the reason.
- 如果检索属性 x.then 导致抛出异常 e,则以 e 为原因拒绝 promise
If
thenis a function, call it withxasthis, first argumentresolvePromise, and second argumentrejectPromise, where:
1. If/whenresolvePromiseis called with a valuey, run[[Resolve]](promise, y).
2. If/whenrejectPromiseis called with a reasonr, rejectpromisewithr.
3. If bothresolvePromiseandrejectPromiseare called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.
4. If callingthenthrows an exceptione,
4.1 IfresolvePromiseorrejectPromisehave been called, ignore it.
4.2 Otherwise, rejectpromisewitheas the reason.
- 如果 then 是一个函数,则使用 x 作为 this 调用它,第一个参数是 resolvePromise,第二个参数是 rejectPromise,其中:
- 如果/当使用值 y 调用 resolvePromise 时,运行 [[Resolve]](promise, y)。
- 如果/当以 r 原因调用 rejectPromise,则用 r 拒绝 Promise。
- 如果同时调用了 resolvePromise 和 rejectPromise,或者对同一个参数进行了多次调用,则第一个调用优先,任何进一步的调用都将被忽略。
- 如果调用然后抛出异常 e, 如果调用了 resolvePromise 或 rejectPromise ,则忽略它。 否则,以 e 为理由拒绝 Promise。
If
thenis not a function, fulfillpromisewithx.
- 如果 then 不是函数,则用 x 实现 Promise。
If x is not an object or function, fulfill promise with
x.
- 如果 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 rejectpromisewith an informativeTypeErroras the reason.
- 如果一个 Promise 用一个 thenable 解决,该 thenable 参与循环 thenable 的链,这样 [[Resolve]](promise, thenable) 的递归性质最终会导致 [[Resolve]](promise, thenable) 再次被调用,上述算法会导致无限递归。 实现鼓励但不要求检测这种递归,并拒绝Promise以有用的 TypeError信息作为原因。
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 链,则永远递归是正确的行为。