原文地址:https://promisesaplus.com
大乐注: 为了使译文简明清晰并更好的表意,原文中的部分术语,译文中并未强行进行翻译
本文是关于 JavaScript Promise 的一个稳定,可互通(interoperable)的开放标准 — 由开发者制定, 为开发者服务
pormise
表示一个异步操作的最终结果。then
方法是与一个 promise
交互的主要方法,该方法通过注册回调函数的形式来接收promise
的value
或其无法被fulfill
的reason
本规范详述了then
方法的行为,为所有符合Promises/A+
规范的promise
实现提供了一个可以依赖、可互通的基础。因此,本规范可以被认为是非常稳定的。尽管Promises/A+
组织可能会偶尔对此规范进行微小的向后兼容的调整来明确一些新发现的边界情况;我们只有在经过严格的考虑,讨论以及测试后,才会引入大型的或非向后兼容的改动。
从历史上看,Promises/A+
明确了此前Promises/A 提案的行为准则,扩展其内容以覆盖一些事实上的行为,并去除了其表意不清或有问题的一些部分
最后,Promises/A+
的核心并没有就如何create
、fulfill
或reject
一个promise
给出明确规范,而是选择专注于提供一个可互通的then
方法。在未来关于配套规范的工作中我们可能会涉及这些主题。
1. Terminology - 术语
- “
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
的状态
一个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
方法
promise
必须提供一个then
方法来获取其当前或最终的value
或reason
pormise
的then
方法接收两个参数:
promise.then(onFulfilled, onRejected)
- 2.2.1
onFulfilled
和onRejected
都是可选参数:- 2.2.1.1 如果
onFulfilled
不是一个函数,它必须被忽略。 - 2.2.1.2 如果
onRejected
不是一个函数,它必须被忽略。
- 2.2.1.1 如果
- 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 如果
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
onFulfilled
或者onRejected
在execution context仅包含平台代码之前不得被调用。[3.1]
- 2.2.5
onFulfilled
和onRejected
只能被作为函数调用(例如:没有this
)。[3.2]
- 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
必须返回一个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
解析流程
Promise
解析流程指接收一个promise
和一个任意值x
作为输入的一个抽象流程,表示为[[Resolve]](promise, x)
。如果x
为thenable
,它会尝试让promise
继承x
的状态,前提是x
至少行为与promise
有一定的相似。否则,它将以x
作为value
来fulfill
这个promise
。
这种处理thenable
的方式允许promise
的不同实现互通,只要他们都暴露一个符合Promises/A+
规范的then
方法。它同时也能支持基于Promises/A+
规范的实现与其它不规范但合理的实现(至少带有一个then
方法)在一定程度上互相兼容
[[Resolve]](promise, x)
按以下步骤执行:
- 2.3.1 如果
promise
和x
引用同一个对象,以TypeError
作为reason
来reject
这个promise
- 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
来fulfill
promise
- 2.3.2.2 如果/当
x
变为rejected
状态,以相同的reason
来reject
promise
- 2.3.2.1 如果
- 2.3.3 反之, 如果
x
是一个object
或function
:- 2.3.3.1 把
then
设置成x.then
。[3.5] - 2.3.3.2 如果访问
x.then
属性导致抛出了一个异常(设为e
),以e
作为reason
来reject
promise
。 - 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
来reject
promise
. - 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
来reject
promise
。
- 2.3.3.3.4.1 如果
- 2.3.3.3.1 如果/当
- 2.3.3.4 如果
then
不是一个函数,以x
作为value
来fulfill
promise
。
- 2.3.3.1 把
- 2.3.4 如果
x
不是object
或function
,将x
作为value
来fulfill
promise
。
如果一个promise
以一个会导致链式循环的thenable
被解析,比如从[[Resolve]](promise, thenable)
开始执行最终导致[[Resolve]](promise, thenable)
再次被执行,遵从以上算法会导致无限递归。我们鼓励,但不强求实现(此规范)时检测这种递归并以一个告知性的TypeError
作为reason
来reject
这个promise
。[3.6]
3. Notes - 注释
3.1 这里的“平台代码”意味着引擎,环境和promise
实现代码。实践中要确保 onFulfilled
和onRejected
方法是异步执行的,且应该在then
方法被调用的那一轮事件循环之后的新执行栈中执行。可以按“宏任务”实现(例如setTimeout
或setImmediate
),也者按“微任务”实现(例如MutationObserver
或process.nextTick
)。由于promise
实现被认为是平台代码,故代码自身在处理在处理程序时可能已经包含一个任务调度队列。
(大乐注:这里需要了解有关宏任务与微任务的概念 -- 简而言之:在本轮事件循环运行完成之前,回调函数不会被调用。)
3.2 也就是说,在严格模式中,函数内this
的值为undefined
;在非严格模式中this
为全局对象。
3.3 (此规范的)实现可以允许promise2 === promise1
,只要其符满足规范内的所有要求。但每一个实现应当在文档中阐明它是否(且在何种情况下)会产生promise2 === promise1
这一情况。
3.4 通常,只有x
和promise
为同一实现时,我们才能知道此条件为真。此条规则允许每个实现使用自己特有的方式来接受已知符合要求的promise
(大乐注:指x
)的状态
3.5 这个针对x.then
的引用先存储 -> 再判断 -> 再调用的过程,可以避免多次访问x
的then
属性。这种预防措施对于保证一致性十分重要,因为x.then
的值可能随着多次检索改变。
3.6 (此规范的)实现不应当对thenable
链的深度故意做出限制并假设超过这一限制值得递归是无限循环。只有真正的循环才应当导致抛出TypeError
;如果出现一条由彼此唯一的theable
组成的无限的链,那么一直无限递归下去是正确的行为。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!