【译】前端知识储备——Promise/A+规范

2018-09-15 admin

概述

自从准备晋级之后,就拖更了很久了,既然晋级弄完了,那么也恢复更新了。

在面试别人的过程中,发现基本上没有人对整个Promise完全了解,因此希望通过这篇文章来帮助大家了解下Promise的全貌。本文的主要内容是Promise/A+规范的译文,主要是能够帮助大家了解下Promise的规范,以及解决在日常运用中遇到的一些问题。

原文地址为:https://promisesaplus.com/#po…

如果需要测试一个Promise库是否符合Promise/A+规范,可以使用这个:https://github.com/promises-a…

原文概览

一个标准声明、可操作的JavaScript Promise——出自开发者,为了开发者。

一个promise代表一个异步操作的最终结果。与promise交互的主要方法是通过它的then函数。这个函数注册一个回调函数来接收promise最终的值(value)或者是没有成功的原因(reason)。

这篇文档详细说明了then方法的具体行为,它为所有的符合Promise/A+规范的实现提供了一个基础的交互。像这样,这个规范应该设计的非常稳定。尽管Promise/A+组织可能偶尔通过一些向后兼容的小修改来调整这个文档来适应新发现的场景,我们只会在经历过了小心的思考、讨论和测试后增加大的、不向后兼容的修改。

从历史上来看,Promise/A+阐述了更早的Promise/A的行为规范,并且在其基础上进行了扩展,覆盖了一些实际行为和之前遗漏的问题。

最终,核心的Promise/A+文档不关心如何去创建、完成(resolve)或者拒绝(reject)一个Promise,而是聚焦在提供一个可交互的then函数。在将来的其他规范中可能会涉及这些没有提及的内容。

1. 术语

1.1. "promise"是一个对象或者函数,它拥有一个符合文档中描述行为的then方法。

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.3. 如果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。

原文链接:https://segmentfault.com/a/1190000016411620

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-40366.html

文章标题:【译】前端知识储备——Promise/A+规范

相关文章
js性能优化 如何更快速加载你的JavaScript页面
确保代码尽量简洁 不要什么都依赖JavaScript。不要编写重复性的脚本。要把JavaScript当作糖果工具,只是起到美化作用。别给你的网站添加大量的JavaScript代码。只有必要的时候用一下。只有确实能改善用户体验的时候用一下。 ...
2015-11-12
2015年JavaScript或“亲库而远框架”
2014年过去了,作为一个JavaScript开发者很难满怀信心的去“挽回”一个特定的库或技术,即便是强大的Angular,似乎也因为最近的一些事情而动摇。 2014年10月的ng-europe会议上,Angular开发者团队透露了一个关于...
2015-11-12
Android中Okhttp3实现上传多张图片同时传递参数
之前上传图片都是直接将图片转化为io流传给服务器,没有用框架传图片。 最近做项目,打算换个方法上传图片。 Android发展到现在,Okhttp显得越来越重要,所以,这次我选择用Okhttp上传图片。 Okhttp目前已经更新到Okhttp...
2017-03-17
JavaScript实现PC手机端和嵌入式滑动拼图验证码三种效果
PC和手机端网站滑动拼图验证码效果源码,同时包涵了弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值,嵌入式Demo,使用表单形式提交二次验证所需的验证结果值,移动端手动实现弹出式Demo三种效果 首先要确认前端使用页面,比如...
2017-03-17
Angular2-primeNG文件上传模块FileUpload使用详解
近期在学习使用Angular2做小项目,期间用到很多primeNG的模块。 本系列将结合实战总结angular2-primeNG各个模块的使用经验。 文件上传模块FileUploadModule 首先要在使用该组件的模块内导入文件上传模块 ...
2017-03-09
React.js编程思想
JavaScript框架层出不穷,在很多程序员看来,React.js是创建大型、快速的Web应用的最好方式。这一款由Facebook出品的JS框架,无论是在Facebook还是在Instagram中,它的表现都非常出色。 使用React.j...
2015-11-12
JavaScript常用特效chm下载
下载地址:JavaScript常用特效chm下载 对了,如果打开空白,在手册上右键属性解除锁定即可。 ...
2015-11-12
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: <!DOCTYPE html> <html lang="en"> <head> ...
2017-03-13
12个你未必知道的CSS小知识
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。 1.CSS的color属性并非只能用于文本显示 对于CSS的color属性,相信所有Web开发人员...
2015-11-12
ajax为什么令人惊异?ajax的优缺点
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。 Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHT...
2015-11-12
回到顶部