自从准备晋级以后,就拖更了好久了,既然晋级弄完了,那么也恢复更新了。javascript
在面试别人的过程当中,发现基本上没有人对整个Promise彻底了解,所以但愿经过这篇文章来帮助你们了解下Promise的全貌。本文的主要内容是Promise/A+规范的译文,主要是可以帮助你们了解下Promise的规范,以及解决在平常运用中遇到的一些问题。java
原文地址为:promisesaplus.com/#point-1git
若是须要测试一个Promise库是否符合Promise/A+规范,可使用这个:github.com/promises-ap… 。github
一个标准声明、可操做的JavaScript Promise——出自开发者,为了开发者。面试
一个promise表明一个异步操做的最终结果。与promise交互的主要方法是经过它的then
函数。这个函数注册一个回调函数来接收promise最终的值(value)或者是没有成功的缘由(reason)。promise
这篇文档详细说明了then
方法的具体行为,它为全部的符合Promise/A+规范的实现提供了一个基础的交互。像这样,这个规范应该设计的很是稳定。尽管Promise/A+组织可能偶尔经过一些向后兼容的小修改来调整这个文档来适应新发现的场景,咱们只会在经历过了当心的思考、讨论和测试后增长大的、不向后兼容的修改。异步
从历史上来看,Promise/A+阐述了更早的Promise/A的行为规范,而且在其基础上进行了扩展,覆盖了一些实际行为和以前遗漏的问题。函数
最终,核心的Promise/A+文档不关心如何去建立、完成(resolve)或者拒绝(reject)一个Promise,而是聚焦在提供一个可交互的then
函数。在未来的其余规范中可能会涉及这些没有说起的内容。测试
1.1. "promise"是一个对象或者函数,它拥有一个符合文档中描述行为的then
方法。this
1.2. "thenable"是一个有then
方法的对象或者函数。
1.3. "value"是一个合法的JavaScript值(包括undefined
, 一个thenable或者一个promise)。
1.4. "exception"是一个使用在throw
语句中的抛出来的值。
1.5. "reason"是一个用来表示promise拒绝的缘由的值。
一个promise必须处于一下三种状态:pending、fulfilled或者rejected。
2.1.1. 当处于pending状态时,promise:
2.1.1.1. 可能会转换成任何其余的状态。
2.1.2. 当处于fulfilled状态时,promise:
2.1.2.1. 禁止转换成其余状态。
2.1.2.2. 必须有一个没法更改的值。
2.1.3. 当处于rejected状态时,promise:
2.1.3.1. 禁止转换成其余状态。
2.1.3.2. 必须有一个没法更改的缘由。
在这里,没法更改意味着全等(例如===
),可是不表明深比较相等。
then
方法promise必须包含一个then
方法来访问它当前或者最终的值或者缘由。
Promise的then
方法接收两个参数:
promise.then(onFulfilled, onRejected)
复制代码
2.1.1. onFulfilled
和onRejected
函数有都有可选的参数:
2.2.1.1. 若是onFulfilled
不是一个函数,那么它必须被忽略掉。
2.2.1.2. 若是onRejected
不是一个函数,那么它必须被忽略掉。
2.2.2. 若是onFulfilled
是一个函数:
2.2.2.1. 它必须在promise
到fulfilled状态后触发,promise
的值是它的第一个参数。
2.2.2.2. 它在一个promise
到fulfilled状态以前禁止被触发。
2.2.2.3. 它禁止被触发屡次。
2.2.3. 若是onRejected
是一个函数:
2.2.3.1. 它必须在promise
到rejected状态后触发,promise
的缘由是它的第一个参数。
2.3.2.2. 它在一个promise
到rejected以前禁止被触发。
2.3.2.3. 它禁止被触发屡次。
2.2.4. onFulfilled
或者onRejected
只有在执行上下文堆栈只有平台代码时才能被触发。
2.2.5. onFulfilled
和onRejected
必须做为函数被调用(例如没有this
值)。
2.2.6. then
方法可能在相同的promise中被调用屡次。
2.2.6.1. 若是promise
到了fullfilled状态,那么全部的onFulfilled
回调函数都必须按照他们原有的顺序进行调用执行。
2.2.6.2. 若是promise
到了rejected状态,那么全部的onRejected
回调函数都必须按照他们原有的顺序进行调用执行。
2.2.7. then
方法必须返回一个promise:
promise2 = promise1.then(onFulfilled, onRejected);
复制代码
2.2.7.1. 若是onFulfilled
或者onRejected
方法返回一个值x
,那么执行promise的解析过程[[Resolve]](promise2, x)
。
2.2.7.2. 若是onFulfilled
或者onRejected
方法抛出一个异常e
,promise2
必须使用e
做为缘由拒绝掉(rejected)。
2.2.7.3. 若是onFulfilled
不是一个函数而且promise1
到了fulfilled状态,那么promise2
必须在与promise1
的值相同的状况下转换到fulfilled状态。
2.2.7.4. 若是onRejected
不是一个函数而且promise1
到了rejected状态,那么promise2
必须在与promise1
的缘由相同的状况下转换到rejected状态。
promise解析函数是一个输入一个promise或者一个值的抽象的操做,咱们表示为[[Resolve]](promise, x)
。若是x
是一个thenable对象,在假定x
的行为至少有点像一个promise的状况下,它会尝试让promise
转换到x
的状态。不然,他会用x
的值完成promise
的状态。
这种thenable对象的方式容许promise实现交互,只要他们暴露一个符合Promise/A+规范的then
函数。它还容许Promise/A+的实现支持一个有合适的then
方法的不兼容的实现。
运行[[Resolve]](promise, x)
,须要遵循如下步骤:
2.3.1. 若是promise
和x
指向同一个对象,那么用TypeError
做为缘由拒绝promise。
2.3.2. 若是x
是一个promise,判断它的状态:
2.3.2.1. 若是x
是pending状态,promise
保留pending状态直到x
变成fulfilled状态或者rejected状态。
2.3.2.2. 若是x
是fulfilled状态,那么用一样的值将整个promise
完成。
2.3.2.3. 若是x
是rejected状态,那么用一样的缘由拒绝promise
。
2.3.3. 不然,若是x
是一个对象或者函数,
2.3.3.1. 让then
变成x.then
。
2.3.3.2. 若是在检测x.then
这个属性的结果时抛出一个异常e
,把e
做为缘由拒绝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
触发,那么用r
来拒绝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
做为缘由拒绝promise
。
2.3.3.4. 若是then
不是一个函数,那么用x
完成promise
。
2.3.4. 若是x
不是一个对象或者函数,那么用x
完成promise
。
若是一个promise是经过在环形的thenable链中的一个thenable来完成的,如递归的[[Resolve]](promise, thenable)
类型再次调用[[Resolve]](promise, thenable)
,遵循上述的规则会致使无穷递归。对这种递归状况的检测而且使用TypeError
做为缘由进行拒绝,咱们鼓励实现,但不要求。
3.1. 在这里"平台代码"(platform code)意味着引擎,环境和promise实现代码。在实践中,这个要求确保了onFulfilled
和onRejected
是异步执行的,then
调用也是在循环以后,有一个新的堆栈信息。这能够经过一个宏任务(macro-task)机制例如setTimeout
或者setImmediate
来实现,也能够经过一个微任务(micro-task)例如MutationObserver
或者process.nextTick
来实现。若是promise的实现考虑平台代码,那么它本身可能会带一个任务执行队列或者“蹦床”来处理被调用状况。
3.2. 在严格模式下,this
是在promise里面将会是undefined
。在松散模型下,他表明的是全局对象。
3.3. 若是实现知足全部要求的话,能够容许promise2 === promise1
。每个实现都应该代表是否支持promise2 === promise1
,若是支持则是须要在什么条件下。
3.4. 一般来讲,若是按照当前的实现方式,咱们只能知道x
是一个真的promise。这一条容许你在具体实现的使用过程当中来判断未知的promise的状态。
3.5. 在程序中,首先存储x.then
的引用,其次测试这个引用,而后再调用这个引用,避免屡次访问x.then
属性。这样的预防措施对于确保那些会在两次访问之间可能变化的属性值获取到一致的结果很是重要。
3.6. 实现中不该该对thenable调用链值设置任意深度限制,而是应该假设这个递归的限制值是无穷大。只有真正的循环才会致使TypeError
;若是遇到了一个长度为无穷大的不一样的thenable,保证在正确的行为下一直递归。
本文主要经过英文翻译为中文的Promise/A+规范,让你们了解了整个规范的所有内容。我会在下一篇博客中给你们带来如何实现一个彻底符合Promise/A+规范的Promise。