Promises/A+ 规范

一个开放的,可交互的由开发者制定的 JavaScript Promise 标准。

一个 Promise 代表一个异步操作的最终结果。与 Promise 交互的主要方式是通过它的 then 方法,该 then 方法注册了两个回调函数,用来接收 Promise 的最终结果或者导致 Promise 不能 fulfilled(已完成) 的原因。

本规范详细的列出 then 方法的行为,为所有符合 Promises/A+ 规范的 Promise 提供了一个可互操作的基础来定义 then 方法。因此本规范是稳定的。尽管 Promise/A+ 组织可能会偶尔地通过一些较小的且向后兼容的修订,来解决新发现的一些边界情况。如果要进行大规模或者不兼容的更新,我们一定会经过仔细的考虑、讨论和测试。

从历史上来说,Promises/A+ 规范实际上是把之前 Promises/A规范中的建议变成了标准:扩展了原有规范约定俗成的行为,并删减了原规范的一些特例情况和有问题的部分

最后 Promises/A+ 规范不设计如何创建、解决和拒绝 promise,而是专注于提供一个可交互操作的 then 方法。未来在其他相关规范中可能会提及。

1、术语

  1. promise” 是一个拥有 then 方法的 对象或者函数,它的行为符合本规范
  2. thenable” 是一个定义了 then 方法的对象和函数
  3. 值(“value”) 是任何 JavaScript 的合法值 (包括 undefined, thenable, 或者 promise).
  4. 异常(“exception”) 是使用 throw 抛出的一个值
  5. 原因(“reason”)是一个 promise 的拒绝原因

2、要求

2.1、Promise 的状态

一个 Promise 的当前状态必须是以下三种状态中的一种:等待(pending),完成(fulfilled)和拒绝(rejected

  1. 当一个promise处于等待状态:
    1. 可以迁移到完成状态或者拒绝状态中的任意一个
  2. 当一个 promise 处于完成状态
    1. 一定不能再迁移到其他状态
    2. 必须有一个值(value),而且一定不能再改变
  3. 当一个 promise 处于拒绝状态
    1. 一定不能再迁移到其他状态
    2. 必须有一个原因(reason),而且一定不能再改变

这里,“一定不能改变” 意味着 恒等 (例如 ===),但是并不意味着更深层次的不可变。

2.2、Then 方法

一个 promise 必须提供一个 then 方法,来访问它当前的最终结果或者原因
一个 promisethen 方法接收2个参数:
promise.then(onFulfilled,onRejected)

  1. onFulfilledonRejected 都是可选参数:
    1. 如果 onFulfilled 不是函数,那它必须被忽略
    2. 如果 onRejected 不是函数,那它必须被忽略
  2. 如果 onFulfilled 是一个函数:
    1. 它必须在 promise 状态变成完成(fulfilled)状态之后才会调用,并且promise的值是第一个参数
    2. 它一定不能在 promise 是完成(fulfilled)状态之前被调用
    3. 它一定不能被调用超过1次
  3. 如果 onRejected 是一个函数
    1. 它必须在 promise状态变成拒绝(rejected)之后才会调用,并且promise的原因是第一个参数
    2. 它一定不能在 promise 是拒绝(rejected)状态之前被调用
    3. 它一定不能被调用超过1次
  4. onFulfilledonRejected 只有在执行上下文栈仅包含平台代码的时候才会被调用 [3.1].
  5. onFulfilledonRejected 必须当作函数调用(例如,没有 this值) [3.2]
  6. 同一个 promisethen 方法可以多次调用
    1. promise是完成(fulfilled)状态,所有相应的onFulfilled 回调必须按照他们初始调用then方法的顺序执行
    2. promise是拒绝(rejected)状态,所有相应的onFulfilled 回调必须按照他们初始调用then方法的顺序执行.
      7.then 方法必须返回一个promise对象 [3.3].
      promise2 = promise1.then(onFulfilled,onRejected);
    3. 如果 onFulfilled 或者 onRejected 返回一个值 x,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)
    4. 如果onFulfilled 或者onRejected 抛出一个异常 e, promise2 必须以 e 为原因被拒绝.
    5. 如果 onFulfilled 不是函数,并且 promise1 是完成状态,那么promise2必须以promise1同样的值完成.
    6. 如果 onReject 不是函数,并且 promise1 是拒绝状态,那么promise2必须以promise1同样的值拒绝.

2.3、Promise 解决过程

Promise 的解决过程是一个抽象操作,需要一个 promise 和一个值来作为输入,我们将其表示为[[Resolve]](promise, x)。如果 x 有 then 方法且看上去像一个 Promise ,那它会尝试让 promise 接收x的状态,否则就用x的值来完成(fulfilled) promise。

这种thenable的特性使得 Promise 的实现更具有通用性:只要其暴露出一个遵循 Promise/A+ 协议的 then 方法即可;这同时也使遵循 Promise/A+ 规范的实现可以与那些不太规范但可用的实现能良好共存。

要运行[[Resolve]](promise, x),需要执行如下步骤:

  1. 如果 promisex 指向同一个对象,那用TypeError为原因拒绝promise
  2. 如果x是一个promise,那就让 promise 接受x的状态 [3.4]:
    1. 如果xpending状态,那promise必须保持pending状态直到x变成完成(fulfilled)或者拒绝(rejected
    2. 如果x是完成态fulfilled, 那让promise 用同样的值(value)完成.
    3. 如果x是拒绝态rejected, 那让promise 用同样的原因(reason)拒绝
  3. x为对象或者函数,
    1. x.then 赋值给 then. [3.5]
    2. 如果检索属性 x.then 导致抛出了一个异常 e,用 e 作为原因拒绝 promise
    3. 如果then是一个函数,用x作为this调用它,第一个参数是 resolvePromise, 第二个参数是rejectPromise:
      1. 如果resolvePromise被一个值y调用,执行[[Resolve]](promise, y).
      2. 如果 rejectPromise 以原因 r为参数被调用,则以原因r拒绝 promise
      3. 如果 resolvePromiserejectPromise 都被调用,或者被同一参数调用了多次,则优先采用第一次调用并剩下的调用都会被忽略
      4. 如果调用抛出异常 e
        1. 如果 resolvePromise 或者 rejectPromise 已经被调用过了,那忽略它
        2. 用异常e为原因拒绝promise
    4. 如果then不是一个函数,用x完成promise
  4. 如果x不是一个对象或者数组,用x完成promise

如果一个 promise 被一个循环的 thenable 链中的对象完成,而 [[Resolve]](promise, thenable)的递归性质又使得其被再次调用,根据上面的算法将会导致无限递归。规范中并没有强制要求处理这种情况,但也鼓励实现者检测这样的递归是否存在,若检测到存在则用一个可识别的 TypeError 为原因来拒绝 promise[3.6]。

3、注释

  1. 这里的平台代码是指引擎、环境以及 promise 的实施代码。在实践中,要确保 onFulfilledonRejected 两个参数异步执行,并且应该在 then方法被调用的那一轮事件循环之后的新执行栈中执行。这可以用如 setTimeoutsetImmediate这样的“宏任务”机制实现,或者用如MutationObserverprocess.nextTick 这样的“微任务”机制实现。由于 promise 的实施代码本身就是平台代码,故代码自身在处理在处理程序时可能已经包含一个任务调度队列
  2. 严格模式下,它们中的this将会是undefined;在非严格模式,this将会是全局对象
  3. 假如实现满足所有需求,可以允许 promise2 === promise1。每一个实现都应该记录是否能够产生promise2 === promise1 以及什么情况下会出现 promise2 === promise1
  4. 总的来说,只有x来自于当前实现,才知道它是一个真正的promise。这条规则允许那些特例实现采用符合已知要求的Promise的状态
  5. 这个程序首先存储x.then的引用,之后测试和调用那个引用,这样避免了多次访问x.then属性。这种预防措施确保了该属性的一致性,因为访问者属性的值可能在俩次检索之间发生变化
  6. 实现不应该在thenable链的深度上做任意限制,并且假设超过那个任意限制将会无限递归。只有真正的循环才应该引发一个TypeError;如果遇到一个无限循环的thenable,永远执行递归是正确的行为
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值