最近在看Nodejs方面的内容,突然想到了Promise,于是想到看看它的标准,手搓一个出来。
这是一篇长文,准备分段更新。


目录

1. 标准

更新日志:
2019年1月21日 完成了标准部分的内容。


标准

先从标准入手,下文为标准的翻译。

术语

  1. Promise对象/函数拥有then方法,其行为符合本规范
  2. thenable表明一个对象/函数拥有then方法
  3. value是一个合法的JavaScript值,包括undefined,thenable和promise
  4. exception是通过throw抛出的value
  5. reason是一个用来表示promise被rejected原因的value

要求

Promise 的状态

  1. Pending
    • 一个Pormise可以过渡到fulfilled或rejected状态。
  2. fulfilled
    • 无法过渡到其他状态
    • 必须有一个不变的value
  3. rejected
    • 无法过渡到其他状态
    • 必须有一个不变的reason

then 方法

Promise必须提供then方法来访问其当前或最终的value或reason。
promise的then方法接受两个参数:

1
promise.then(onFulfilled, onRejected);
  1. onFulfilled和onRejected都是可选参数
    • 如果onFulfilled不是函数,其将会被忽略
    • 如果onRejected不是函数,其将会被忽略
  2. 如果onFulfilled是函数
    • 它必须在fulfilled之后被调用,以promise的value作为它的第一个参数
    • 它不能在fulfilled之前调用
    • 它不能调用超过一次
  3. 如果onRejected是函数
    • 它必须在rejected之后被调用,以promise的reason作为它的第一个参数
    • 它不能在rejected之前调用
    • 它不能调用超过一次
  4. onFulfilled or onRejected must not be called until the execution context stack contains only platform code.
    这段不大理解。

  5. onFulfilled和onRejected必须作为函数调用(比如没有this)
  6. then在一个promise中可调用多次
    • 如果fulfilled,所有相应的onFulfilled必须根据它们调用then的顺序被执行
    • 如果rejected,所有相应的onRejected必须根据它们调用then的顺序被执行
  7. then必须返回一个promise

    1
    promise2 = promise1.then(onFulfilled, onRejected);
    • 如果任意onFulfilled或onRejected返回了x,运行该Promise解决过程:[[Resolve]](promise2, x)
    • 如果任意onFulfilled或onRejected抛出了e,promise2必须为rejected,且以e作为reason
    • 如果onFulfilled不是一个函数,而promise1已经fulfilled,则promise2必与promise1所fulfilled的value一致
    • 如果onRejected不是一个函数,而promise1已经rejected,则promise2必与promise1所rejected的reason一致

Promise 解决过程

Promise解决过程是一个抽象操作,它将promise和value作为输入,我们将其表示为[[Resolve]](promise, x)。如果x是thenable的,它会尝试采用x的状态(假设x至少运作地与promise相似),否则它以x的值fulfill。

对thenables的这种处理使得promise实现之间能够相互操作,只要它们公开符合Promises/A+的方法即可。它还允许Promises/A+实现使用合理的方法“同化”不一致的实现。

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

  1. 如果promise和x对应的是同一个对象,以TypeError来reject这个promise
  2. 如果x是一个promise,采用它的state
    • 如果x为pending,那么在其被fulfilled或rejected之前,promise必须保持pending状态
    • 如果x被fulfilled,以相同的value来fulfill这个promise
    • 如果x被rejected,以相同的reason来rejected这个promise
  3. 如果x是对象或函数
    • 使then成为x.then
    • 如果检索属性x.then时抛出异常e,以e为reason来reject这个promise
    • 如果then是一个函数,则以x作为this调用它,第一个参数为resolvePromise,第二个参数为rejectPromise,其中:
      1. 如果使用value y调用resolvePromise,运行[[Resolve]](promise, y)
      2. 如果使用reason r调用rejectPromise,以r来reject该promise
      3. 如果resolvePromise和rejectPromise都被调用,或者对同一参数进行多次调用,则以第一次调用为准,忽略之后的调用。
      4. 如果调用then抛出了异常e
        • 如果resolvePromise或者rejectPromise已被调用,忽略
        • 否则,以e作为reason来reject该promise
    • 如果then不是函数,以x来fulfill该promise
  4. 如果x不是对象或函数,以x来fulfill该promise

If a promise is resolved with a thenable that participates in a circular thenable chain, such that the recursive nature of [[Resolve]](promise, thenable)eventually causes[[Resolve]](promise, thenable) to be called again, following the above algorithm will lead to infinite recursion. Implementations are encouraged, but not required, to detect such recursion and reject promise with an informative TypeError as the reason. [3.6]