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


目录

1. 标准

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


标准

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

术语

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

要求

Promise 的状态

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

then 方法

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

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

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

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

Promise 解决过程

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

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

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

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

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]