原文地址:https://promisesaplus.com/

本篇为原文翻译+个人理解,若有谬误请各位指正,谢谢。

尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/4139172.html  ^_^肥仔John

一个可靠的可共同协作的JavaScript Promise开放标准

promise代表一个异步操作的最终结果。主要通过promise的then方法订阅其最终结果的处理回调函数,和订阅因某原因无法成功获取最终结果的处理回调函数。

本说明将详述then方法的行为特点,符合Promise/A+规范的promise实现均以then方法为交互核心。Promises/A+组织会因新发现的问题以向后兼容的方式修改规范,且每次修改均会经过严格的考虑、讨论和测试,因此Promises/A+规范相对来说还是比较稳定的。

Promises/A+是在Promises/A的基础上对原有规范进行修正和增强。

最后,本说明并不涉及如何创建、fulfill或reject promises,而是着重介绍then方法。将来或许在其他说明中涉及这些内容。

1. 术语                                        

1.1. "promise"拥有then方法且符合Promises/A+标准的对象。

1.2. "thenable"拥有thne方法的对象。

1.3. "value"合法的JavaScript对象(包括undefined,thenable对象,promise对象)。

1.4. "exception"通过throw语句抛出的值。

1.5. "reason"合法的JavaScript对象,表示promise状态转换为rejected的原因。

2. 需求                                        

  2.1. Promise状态

promise状态为pending,fulfilled和rejected中的其中一种。

2.1.1. 当promise状态为pending时:

2.1.1.1. promise的状态可以转换为fulfilled或rejected。

  2.1.2. 当promise状态为fulfilled时:

2.1.2.1. 无法转换为其他状态。

2.1.2.2. 必须有一个不可改变的值作为onFulfilled事件处理函数的入参

2.1.3. 当promsie状态为rejected时:

   2.1.2.1. 无法转换为其他状态。

2.1.2.2. 必须有一个不可改变的值作为onRejected事件处理函数的入参

上述不可改变的值是指value或reason变量所存储的值或地址不变,而不是指地址所指向的堆空间内的对象属性等不可变。

  2.2. then方法

promise必须提供then方法用于订阅状态转换事件,从而获取最终值或失败原因。

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状态为fulfilled时才能被调用(晚绑定依然会被调用),并且promise的不可变值将作为 onFulfilled函数 的入参。

2.2.2.2. 在promise状态转换为fulfilled前禁止被调用。

2.2.2.3. 只能被调用一次。

2.2.3.  如果 onRejected 为函数时:

2.2.3.1. 当且仅当promise状态为rejected时才能被调用(晚绑定依然会被调用),并且promise的不可变值将作为 onRejected函数 的入参。

2.2.3.2. 在promise状态转换为rejected前禁止被调用。

2.2.3.3. 只能被调用一次。

2.2.4.  onFulfilled 和 onRejected 当且仅当执行上下文栈中仅包含平台代码[3.1]时才执行

2.2.5.  onFulfilled 和 onRejected 必须以函数的形式来调用(也就是 this对象 在sloppy模式下为全局对象,strict模式下为undefined)[3.2]

2.2.6.  同一个promise的then方法可被多次调用

2.2.6.1. 当promise状态为fulfilled时,将按调用then方法的顺序执行 onFulfilled函数 。

2.2.6.2. 当promise状态为rejected时,将按调用then方法的顺序执行 onRejected函数 。

2.2.7. then方法必须返回一个promise实例[3.3]

promise2 = promise1.then(onFulfilled, onRejected);

2.2.7.1. 如果 onFulfilled 或 onRejected 函数返回值为x,那么执行Promise处理过程 [[Resolve]](promise2, x) 。

2.2.7.2. 如果 onFulfilled 或 onRejected 函数抛出异常e,那么promise2将执行 reject(e) 。

2.2.7.3. 如果 promise1的 onFulfilled 不是函数,那么promise1的不可变值将传递到promise2并作为promise2的不可变值。

2.2.7.4. 如果 promise1的 onRejected不是函数,那么promise1的不可变原因将传递到promise2并作为promise2的不可变原因,并作为promise2的 onRejected 的入参。

  2.3. Promise处理过程

Promise处理步骤是对表示形式为 [[Resolve]](promise, x) 的状态事件处理函数的返回值的抽象处理。如果x为thenable对象,由于thanble对象的行为特性类似于一个promise实例,因此让x来设置promise的状态。若x为其他类型则设置promise的状态为fulfilled并且不可变值为x。

[[Resolve]](promise, x) 的处理过程如下:

2.3.1. 如果promise和x指向同一个对象,则将promise的状态转换为rejected并且以TypeError作为不可变原因。

2.3.2. 如果x是一个promise实例,则以x的状态作为promise的状态[3.4]

  2.3.2.1. 如果x的状态为pending,那么promise的状态也为pending,直到x的状态变化而变化。

2.3.2.2. 如果x的状态为fulfilled,promise的状态也为fulfilled,并且以x的不可变值作为promise的不可变值。

2.3.2.3. 如果x的状态为rejected,promise的状态也为rejected,并且以x的不可变原因作为promise的不可变原因。

2.3.3. 如果x是对象或函数

2.3.3.1. 将x.then赋值给变量then[3.5]

2.3.3.2. 如果在获取属性x.then时抛出异常,则将promise的状态转换为rejected并且以e作为promise的不可变原因。

2.3.3.3. 如果then为函数类型,则以x作为then函数内部的this指针,以promise的resolvePromise和rejectPromise作为入参调用then函数。

  2.3.3.3.1. 如果以y作为入参调用resolvePromise,那么则执行Promise处理过程 [[Resolve]](promise, y) 。

2.3.3.3.2. 如果以r作为入参调用rejectPromise,那么则将promise状态转换为rejected并且以r作为promise的不可变原因。

     2.3.3.3.3. resolvePromise和rejectPromise仅有一个能被调用,且仅能调用一次,重复调用均视作无效操作。

     2.3.3.3.4. 如果调用then方法抛出异常

      2.3.3.4.1. 如果resolvePromise或rejectPromise已经被调用后才抛出异常,则无视。

      2.3.3.4.2. 其他情况则将promise状态转换为rejected并且以异常对象e作为promise的不可变原因。

2.3.3.4. 如果then不是函数,则将promise状态转换为fulfilled并且以x作为promise的不可变值。

2.3.4.如果x不是对象或函数,则将promise状态转换为fulfilled并且以x作为promise的不可变值。

假如不断以Promise或thenable作为onFulfilled的返回值,那么就会进入Promise处理过程的死循环中,虽然Promise/A+规范并没有明确规定具体实现需要通过对死循环进行返回TypeError异常的处理,但实现者可以自行考虑该情况的处理方式。[3.6]

3. 备注                                        

3.1. 这里的“平台代码”是指引擎、执行环境和promise实现代码。实际上,是要求 onFulfilled 和 onRejected 函数为异步执行。浏览器可通过 setTimeout 或 setImmediate ,nodejs可通过 MutationObserver 或 process.nextTick 将函数调度到event loop队列中达到异步执行的效果。

3.2. 在strict模式下this指针为undefined,而在sloppy模式下this指针为全局对象。

3.3. 具体实现可允许promise2===promise1,并且需要将promise2===promise1的条件以文档形式标注说明。

3.4. x为真正的promise实例。

3.5. 由于考虑到ES5的getter特性可能会产生副作用,因此在获取x.then属性时,应该形如以下方式,防止多次调用x.then。

var then = x.then;
typeof(then) === 'function' && then.call(x, resolvePromise, rejectPromise)

3.6.具体实现武断地限制Promise处理过程的递归深度,只有真正的死循环才抛出TypeError异常。如果允许无限循环,也是没问题的。

版权所有:Promises/A+组织

前端翻译:Promises/A+规范的更多相关文章

  1. 【翻译】Promises/A+规范

    目录 介绍 译文 1. 术语(Terminology) 2. 要求(Requirements) 2.1 Promise状态 2.2 then方法 2.3 Promise解析程序 3. 注释 3.1 p ...

  2. CommonJS Promises/A规范

    本文来自四火哥的翻译 CommonJS是一组javascript编程规范,而promise是其中之一. 简而言之,promises是一种令代码的异步行为变得更加优雅的软件抽象.在基本的定义中,代码可能 ...

  3. 一起学习造轮子(一):从零开始写一个符合Promises/A+规范的promise

    本文是一起学习造轮子系列的第一篇,本篇我们将从零开始写一个符合Promises/A+规范的promise,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Pr ...

  4. 对 Promises/A+ 规范的研究 ------引用

    作为 Modern JavaScript 基础设施的一部分,Promises 对前端开发者而言异常重要.它是 async/await 语法的基础,是 JavaScript 中处理异步的标准形式.并且, ...

  5. JavaScript中Promises/A+规范的实现

    Promises是一种异步编程模型,通过一组API来规范化异步操作,这样也能够让异步操作的流程控制更加容易. 下面的代码是假设执行一个异步队列,每一项都会使用上一项返回的数据: function ne ...

  6. JS魔法堂:剖析源码理解Promises/A规范

    一.前言 Promises/A是由CommonJS组织制定的异步模式编程规范,有不少库已根据该规范及后来经改进的Promises/A+规范提供了实现 如Q, Bluebird, when, rsvp. ...

  7. 团队开发前端VUE项目代码规范

    团队开发前端VUE项目代码规范 2018年09月22日 20:18:11 我的小英短 阅读数 1658   一.规范目的: 统一编码风格,命名规范,注释要求,在团队协作中输出可读性强,易维护,风格一致 ...

  8. Promises/A+规范

    为什么需要异步编程方式 一个函数执行之后,在它后面顺序编写的代码中,如果能够直接使用它的返回结果或者它修改之后的引用参数,那么我们通常认为该函数是同步的. 如果一个函数的执行结果或者其修改的引用参数, ...

  9. web前端开发CSS命名规范参考

    做为一个web前端工程师,每天接触HTML.css就像吃饭一样,但是作为一名合作.优秀的web前端工程师,对DIV+CSS命名还是有一定的规范的,本文整理了一份web前端开发中DIV+CSS各种命名规 ...

随机推荐

  1. 源代码安装 MySQL 5.6.28

    本文内容 创建 MySQL 用户和组 解压 MySQL 源代码包 生成配置安装文件 编译和安装 MySQL 配置文件 创建 MySQL 授权表 MySQL 目录授权 启动 MySQL 验证 MySQL ...

  2. Test Tex

    \begin{equation}\label{exampleone}r = r_F+ \beta (r_M - r_F) + \epsilon\end{equation}

  3. sqlserver row_number 类似 mysql中 limit 用法

    select * from ( select row_number() over(ORDER BY inspecdate desc,inspectime DESC,itemorder asc ) as ...

  4. Ubuntu server解决不能访问外网问题

    Ubuntu server解决不能访问外网问题 在Ubuntu Server上设置访问外网时,需要设置dns,通常是将dns添加到/etc/resolv.conf文件中. 但是将dns添加至/etc/ ...

  5. Oracle 12c

    Common User vs. Local User – 12c Edition http://dbasolved.com/2013/06/29/common-user-vs-local-user-1 ...

  6. 加快Bitmap的访问速度

    引言 在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel, 如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操 ...

  7. ubuntu(Mint-17)修改dns

    国内默认dns常被劫持,所以需要修改: $ sudo vi /etc/network/interfaces 在下面添加一行: dns-nameservers 8.8.8.8 8.8.4.4 然后,网上 ...

  8. java 使用 ScriptEngineManager 解析逻辑表达式

    将表达式替换成js使用的文本格式.然后带入eval函数. public class JieXi { public static void main(String[] args) throws Exce ...

  9. C# 开发者代码审查清单【转】

    这是为C#开发者准备的通用性代码审查清单,可以当做开发过程中的参考.这是为了确保在编码过程中,大部分通用编码指导原则都能注意到.对于新手和缺乏经验(0到3年工作经验)的开发者,参考这份清单编码会很帮助 ...

  10. 【学】常用hash算法的介绍

    基本知识 Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映 ...