俗话说好记性不如烂笔头,因此我决定翻译一下Promise/A+
规范,帮助本身更加深入的理解promise
,为以后手撸promise
源码作准备,同时也但愿本篇文章对你们也有所帮助。前端
这是一个实现者为实施者提供的开源的、可互操做的JavaScript Promise规范git
promise
表明一个异步操做的最终结果。与promise
的主要互动方式是经过then
方法注册回调函数来接收promise
的最终值或者promise
未完成的缘由。github
该规范详细描述了then
方法的行为,它提供了一个可互操做的基础,全部Promises/A +
符合 promise
的实现均可以依赖于这个基础。所以,该规范被认为是很是稳定的。尽管Promises/A+
的做者可能偶尔会修改规范,对其进行一些向后兼容的小修改,以解决新发现的问题,咱们只有在仔细考虑、讨论和测试后,才会集成大型或者不向后兼容的变动。web
历史上,Promises/A+
澄清了早期的Promises/A proposal的行为条款,将其拓展到涵盖事实的行为,而且省略了未指定或有问题的部分。算法
最后,Promises/A+
规范的核心不是处理如何建立、完成或者失败的promises
,而是选择专一于一个可互操做的then
方法。将来在配套规范中的工做可能会涉及这些主题。promise
1.1 promise
是具备then
方法的对象或者函数,其行为符合规范。app
1.2 thenable
是定义在then
方法上的对象或者函数。异步
1.3 value
是任何合法的JavaScript
值(包括undefined
,thenable
,或者promise
)函数
1.4 exception
是使用抛出语句抛出的值学习
1.5 reason
是一个代表promise
为何失败的值
2.1.1 当promise
状态为pending
时:
2.1.2 当promise
状态为fulfilled
时:
2.1.2.1 不能变为任何一种状态
2.1.2.2 必须有一个value
,这个value
不能改变
2.1.3 当promise
为rejected
时:
2.1.3.1 不能变为任何一种状态
2.1.3.2 必须有一个reason
,这个reason
不能改变
promise
必须提供一个then
方法,来访问它当前或最终的value
或reason
。
一个promise
的then
方法接收两个参数:
promise.then(onFulfilled, onRejected)
复制代码
2.2.1 onFulfilled
和onRejected
都是可选的参数
2.2.1.1 若是onFulfilled
不是函数,必须被忽略
2.2.1.2 若是onRejected
不是函数,必须被忽略
2.2.2 若是onFulfilled
是一个函数
2.2.2.1 它必须在promise
完成后被调用,而后把promise
的值做为它的第一个参数
2.2.2.2 它不能在promise
完成前被调用。
2.2.2.3 它不能被调用超过一次。
2.2.3 若是onRejected
是一个函数
2.2.3.1 它必须在promise
失败后被调用,而后把promise
的值做为它的第一个参数
2.2.3.2 它不能在promise
失败前被调用。
2.2.3.3 它不能被调用超过一次。
2.2.4 在执行上下文堆栈(execution context)仅包含平台代码以前,不得调用 onFulfilled
和onRejected
[3.1]
2.2.5 onFulfilled
和onRejected
必须做为函数调用(即没有this
值)[3.2]
2.2.6 then
方法可能在同一次promise
中被调用屡次
2.2.6.1 若是/当promise
完成时,全部相应的onFulfilled
回调必须按照最原始的then
顺序来执行
2.2.6.2 若是/当promise
失败时,全部相应的onRejected
回调必须按照最原始的then
顺序来执行
2.2.7 then
方法必须返回一个promise
promise2 = promise1.then(onFulfilled, onRejected);
2.2.7.1 若是onFulfilled
和onRejected
返回一个值x
,请运行Promise Resolution Procedure [[Resolve]](promise2, x)
2.2.7.2 若是onFulfilled
和onRejected
抛出一个异常e
,promise2
必须拒绝并将e
做为reason
2.2.7.3 若是onFulfilled
不是一个函数,且promise1
为完成状态,promise2
必须使用与promise1
相同的value
完成
2.2.7.4 若是onRejected
不是一个函数,且promise1
为失败状态,promise2
必须使用与promise1
相同的reason
完成
promise
解析过程是一个以输入promise
和value
的抽象操做,咱们记做[[Resolve]](promise, x)
,若是x
是thenable
,假设x
的行为有点像promise
,它会尝试让promise
采用x
的状态。不然,它将使用x
值来完成promise
。
只要有实现Promises/A+
兼容的then
方法,对thenable
的处理容许使用promise
实现可以互操做。它还容许Promises/A+
实现使用合理的then
方法“同化”不一致的实现。
运行[[Resolve]](promise, x)
,执行如下的步骤:
2.3.1 若是promise
和x
引用同一个对象,则用TypeError
做为reason
拒绝promise
2.3.2 若是x
是一个promise
,则采用它的状态[3.4]
2.3.2.1 若是x
为pending
状态,promise
必须保持pending
状态直到x
成功或者失败
2.3.2.2 若是x
为完成状态,用相同的值完成promise
2.3.2.3 若是x
为失败状态,用相同的reason
拒绝promise
2.3.3 若是x
是一个对象或函数
2.3.3.1 让then
为x.then
[3.5]
2.3.3.2 若是检索属性x.then
的结果抛出一个异常e
,用e
做为reason
拒绝promise
2.3.3.3 若是then
是一个函数,把x
做为this
调用它,第一个参数resolvePromise
和第二个参数rejectPromise
,其中:
2.3.3.3.1 若是resolvePromise
被y
值调用,运行[[Resolve]](promise, y)
2.3.3.3.2 若是rejectPromise
被为r
的reason
调用,用r
来拒绝promise
2.3.3.3.3 若是 resolvePromise
和rejectPromise
都被调用,或者对同一个参数进行屡次调用,则第一次调用优先,任何进一步的调用被忽略
2.3.3.4 若是then
不是函数,用x
来完成promise
2.3.4 若是x
不是对象或者函数,用x
来完成promise
若是使用参与循环的可循环链的可转换组件解决了一个promise
,这样,[[Resolve]](promise, thenable)
的递归性质致使了再次调用[[Resolve]](promise, thenable)
,遵循上述算法将致使无限递归。鼓励(但不是必须)实现来检测这种递归且用包含信息的TypeError
做为reason
拒绝promise
。[3.6]
这里的“平台代码”是指引擎,环境和promise
实现代码。在实践中,这个需求确保onFulfilled
和onRejected
异步执行,在事件循环以后调用then
,而且使用一个新栈。这能够经过setTimeout
或者setImmediate
宏任务机制,或者使用MutationObserver
或者process.nextTick
微任务机制来实现。因为promise
实现被视为平台代码,所以它自己可能包含一个任务调度队列或“蹦床”在其中调用处理程序。
也就是说,在严格模式下,this
为undefined
,在宽松模式中,它是一个全局对象(global object
)
在知足全部需求的状况下,能够容许实现promise2 === promise1
,每一个实现都应该记录它是否可以产生promise2 === promise1
以及在何种条件下产生
一般,只有x
来自于当前实例时,才知道它是一个真正的promise
,此条款容许使用特定的实现方法来采用已知符合promise
的状态。
这个过程首先存储对x.then
的引用,而后测试,而后调用这个引用。避免了对x.then
属性的屡次访问。这些预防措施对于确保访问者属性的一致性很是重要,由于访问者属性的值可能在两次检索之间发生变化。
实现不该该对thenable
链的深度设置任何限制,并假设递归超出限制。只有真正的循环才会致使TypeError
,若是遇到无穷多个thenable
链,那么永远递归是正确的行为。
熟悉promise
规范有助于咱们深入理解promise
原理,为以后看源码,手写源码铺路~好久不碰英语了,很长时间以后第一次作翻译,若是有翻译很差的地方,还但愿指出~咱们共同窗习,共同进步~
最后,分享一下个人公众号「web前端日记」,若是想更加及时的看见文章,立刻就去关注哇😍