本文根据官网文档翻译,能力有限,有问题欢迎指正


概述

  Promises是一个可靠并可交互的JavaScript标准;被开发者制定,供所有开发者参考。
  promsise表示异步操作的最终结果,通过then方法进行主要交互,该方法可注册两个回调方法(1、接受promise最终值 2、接受promise失败的错误原因)
  此规范详细的规定了then方法的实现,为所有遵循Promises/A+规范的promises实现提供可靠的基础,因此可以认为该规范是非常稳定的,尽管Promises/A+组织偶尔可能会修改此规范,但是都是采用较小的向后兼容方式来解决一些极端情况,同时会经过仔细考虑、讨论和测试后,我们才会集成大型或向后不兼容的修改。
  从历史来看,Promises/A+规范接受了早期的一些建议,同时扩展了一些好的规则,去掉了原规范的特殊情况和有问题的部分
  最后,Promises/A+核心规范并没有涉及如何创建、解决或者拒绝promise,而是选择专注提供可通用的then方法,对于上述操作promise方法可能在其他规范中提及。

1. 术语


  1.1. “promise”是一个具有then方法的对象或者函数,其行为遵循Promises/A+规范
  1.2. “thenable”是一个定义then方法的对象或者函数
  1.3. “value”是任意的JavaScript变量(包括undefined,thenable或promise对象)
  1.4. “exception”是使用throw语句抛出的一个值
  1.5. “reason”是一个promise被rejected的说明

2. 要求


 2.1. promise状态-必须是以下三种状态中的一种,等待状态(pending)、已完成(fulfilled)和 被拒绝(rejected)

  2.1.1. 当promise处于pending时:
   2.1.1.1. 只能改变成fulfilled或者rejected
  2.1.2. 当promise处于fulfilled时:
   2.1.2.1. 不能改变成其他任何状态
   2.1.2.2. 必须有一个值,并且不能改变
  2.1.3. 当promise处于rejected时:
   2.1.3.1. 不能改变成其他任何状态
   2.1.3.2. 必须有一个被拒绝原因,并且不能改变
 这里,‘不可变’意味着恒等(即===),当时不意味着深层次恒等(比如说复杂类型,其属性可以改变)

 2.2. then方法-一个promise必须提供then方法,以便能访问当前状态、终值或被拒原因,then方法接受两个参数;

1
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的终值
   2.2.2.2. 如果promise没有fulfilled之前,不能被调用
   2.2.2.3. 这个方法只能被调用一次
  2.2.3. 如果onFulfilled是一个方法:
   2.2.3.1. 如果promise状态为rejected,这个方法必须被执行,并且第一个参数必须是promise的被拒绝的原因
   2.2.3.2. 如果promise没有rejected之前,不能被调用
   2.2.3.3. 这个方法只能被调用一次
  2.2.4. onFulfilled和onRejected必须在执行环境堆栈仅包含平台代码时才可被调用[3.1]
  2.2.5. onFulfilled和onRejected必须作为函数被调用[3.2]
  2.2.6. then方法可以在一个promise上执行多次:
   2.2.6.1. 如果promise是fulfilled时候,所有onFulfilled将按照传入then方法的顺序依次执行
   2.2.6.2. 如果promise是rejected时候,所有onRejected将按照传入then方法的顺序依次执行
  2.2.7. then方法必须返回一个promise[3.3]:
1
promise2 = promise1.then(onFulfilled, onRejected);
   2.2.7.1. 如果onFulfilled或onRejected返回一个x, 则运行下面的 promise解决过程。
   2.2.7.2. 如果onFulfilled或onRejected抛出一个异常e, promise2必须执行rejected,并带着错误原因e。
   2.2.7.3. 如果onFulfilled不是一个方法以及promise1状态是fulfilled, 那么promise2状态也必须是fulfilled,并且返回和promise1一样的值
   2.2.7.4. 如果onRejected不是一个方法以及promise1状态是rejected, 那么promise2状态也必须是rejected,并且返回和promise1一样的拒绝原因

 2.3. promise解决过程

   promise解决过程是抽象的,它promoise和value做为输入,我们称之为[[Resolve]](promise, x),如果x具有then方法以及看上去像一个promise,就可以尝试使promise接受x的状态,否则用x的值来执行promise。
   这种 thenable 的特性使得 Promise 的实现更具有通用性:只要其暴露出一个遵循 Promise/A+ 协议的 then 方法即可;这同时也使遵循 Promise/A+ 规范的实现可以与那些不太规范但可用的实现能良好共存。
   去执行[[Resolve]](promise, x),需要遵循以下步骤:
  2.3.1. 如果promise和x指向同一个对象,将rejected同时抛出一个typeError做为原因
  2.3.2. 如果x是一个promise,将使promise接受x的状态[3.4]
   2.3.2.1. 如果x状态为pending,就让promise状态也是pending,直到x变为fulfilled或者rejected
   2.3.2.2. 如果x状态为fulfilled,则用相同的值去触发promise的fulfilled改变
   2.3.2.3. 如果x状态为rejected,则用相同的拒绝原因去触发promise的rejected改变
  2.3.3. 如果x是一个对象或者函数
   2.3.3.1. 把 x.then 赋值给 then[3.5]
   2.3.3.2. 如果x状态为fulfilled,则用相同的值去触发promise的fulfilled改变
   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.4. 如果 x 不为对象或者函数,以 x 为参数执行 promise
  如果一个 promise 被一个循环的 thenable 链中的对象解决,而 [[Resolve]](promise, y) 的递归性质又使得其被再次调用,根据上述的算法将会陷入无限递归之中。算法虽不强制要求,但也鼓励开发者检测这样的递归是否存在,若检测到存在则以一个可识别的 TypeError 为拒绝原因来拒绝 promise [3.6]

3. 注释


   [3.1] 这里的平台代码指的是引擎、环境以及 promise 的实施代码。实践中要确保 onFulfilled 和 onRejected 方法异步执行,且应该在 then 方法被调用的那一轮事件循环之后的新执行栈中执行。这个事件队列可以采用“宏任务(macro-task)”机制或者“微任务(micro-task)”机制来实现。由于 promise 的实施代码本身就是平台代码,故代码自身在处理在处理程序时可能已经包含一个任务调度队列。
   [3.2] 也就是说在严格模式(strict)中,函数 this 的值为 undefined ;在非严格模式中其为全局对象。
   [3.3] 如果代码实现满足了规范的所有要求,可以允许 promise2 === promise1 。同时要文档说明在何种条件下允许 promise2 === promise1。
   [3.4] 一般来说,只有当 x 符合当前实现,我们才认为它是真正的 promise 。这一规则允许那些特例实现接受符合已知要求的 Promises 状态。
   [3.5] 这个过程首先存储一个指向 x.then 的引用,然后测试并调用该引用,以避免多次访问 x.then 属性。这种预防措施确保了该属性的一致性,因为其值可能在检索调用中被改变。
   [3.6] 实现不应该对 thenable 链的深度设限,并假定超出本限制的递归就是无限循环。只有真正的循环递归才应能导致 TypeError 异常;如果一条无限长的链上 thenable 均不相同,那么递归下去永远是正确的行为。