[译]前端基础知识储备——Promise/A+规范

概述

自从准备晋级以后,就拖更了好久了,既然晋级弄完了,那么也恢复更新了。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.1. "promise"是一个对象或者函数,它拥有一个符合文档中描述行为的then方法。this

1.2. "thenable"是一个有then方法的对象或者函数。

1.3. "value"是一个合法的JavaScript值(包括undefined, 一个thenable或者一个promise)。

1.4. "exception"是一个使用在throw语句中的抛出来的值。

1.5. "reason"是一个用来表示promise拒绝的缘由的值。

2. 要求

2.1 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. 必须有一个没法更改的缘由。

在这里,没法更改意味着全等(例如===),可是不表明深比较相等。

2.2 then方法

promise必须包含一个then方法来访问它当前或者最终的值或者缘由。

Promise的then方法接收两个参数:

promise.then(onFulfilled, onRejected)
复制代码

2.1.1. onFulfilledonRejected函数有都有可选的参数:

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. onFulfilledonRejected必须做为函数被调用(例如没有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方法抛出一个异常epromise2必须使用e做为缘由拒绝掉(rejected)。

2.2.7.3. 若是onFulfilled不是一个函数而且promise1到了fulfilled状态,那么promise2必须在与promise1的值相同的状况下转换到fulfilled状态。

2.2.7.4. 若是onRejected不是一个函数而且promise1到了rejected状态,那么promise2必须在与promise1的缘由相同的状况下转换到rejected状态。

2.3. promise解析函数

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. 若是promisex指向同一个对象,那么用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. 若是resolvePromiserejectPromise都被调用,或者使用相同的参数屡次调用,那么第一次调用生效,其余以后的任何调用都忽略掉。

2.3.3.3.4. 若是在调用then方法时抛出了一个异常e,

2.3.3.3.4.1. 若是resolvePromiserejectPromise已经被调用了那么就忽略掉它。

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. 注意事项

3.1. 在这里"平台代码"(platform code)意味着引擎,环境和promise实现代码。在实践中,这个要求确保了onFulfilledonRejected是异步执行的,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。

相关文章
相关标签/搜索