最近在看Nodejs方面的内容,突然想到了Promise,于是想到看看它的标准,手搓一个出来。
这是一篇长文,准备分段更新。
目录
1. 标准
更新日志:2019年1月21日 完成了标准部分的内容。
标准
先从标准入手,下文为标准的翻译。
术语
Promise对象/函数拥有then方法,其行为符合本规范thenable表明一个对象/函数拥有then方法value是一个合法的JavaScript值,包括undefined,thenable和promiseexception是通过throw抛出的valuereason是一个用来表示promise被rejected原因的value
要求
Promise 的状态
Pending- 一个
Pormise可以过渡到fulfilled或rejected状态。
- 一个
fulfilled- 无法过渡到其他状态
- 必须有一个不变的
value
rejected- 无法过渡到其他状态
- 必须有一个不变的
reason
then 方法
Promise必须提供then方法来访问其当前或最终的value或reason。promise的then方法接受两个参数:
1 | promise.then(onFulfilled, onRejected); |
onFulfilled和onRejected都是可选参数- 如果
onFulfilled不是函数,其将会被忽略 - 如果
onRejected不是函数,其将会被忽略
- 如果
- 如果
onFulfilled是函数- 它必须在
fulfilled之后被调用,以promise的value作为它的第一个参数 - 它不能在
fulfilled之前调用 - 它不能调用超过一次
- 它必须在
- 如果
onRejected是函数- 它必须在
rejected之后被调用,以promise的reason作为它的第一个参数 - 它不能在
rejected之前调用 - 它不能调用超过一次
- 它必须在
onFulfilled or onRejected must not be called until the execution context stack contains only platform code.
这段不大理解。onFulfilled和onRejected必须作为函数调用(比如没有this)then在一个promise中可调用多次- 如果
fulfilled,所有相应的onFulfilled必须根据它们调用then的顺序被执行 - 如果
rejected,所有相应的onRejected必须根据它们调用then的顺序被执行
- 如果
then必须返回一个promise1
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)要执行如下步骤:
- 如果
promise和x对应的是同一个对象,以TypeError来reject这个promise - 如果
x是一个promise,采用它的state- 如果
x为pending,那么在其被fulfilled或rejected之前,promise必须保持pending状态 - 如果
x被fulfilled,以相同的value来fulfill这个promise - 如果
x被rejected,以相同的reason来rejected这个promise
- 如果
- 如果
x是对象或函数- 使
then成为x.then - 如果检索属性
x.then时抛出异常e,以e为reason来reject这个promise - 如果
then是一个函数,则以x作为this调用它,第一个参数为resolvePromise,第二个参数为rejectPromise,其中:- 如果使用
value y调用resolvePromise,运行[[Resolve]](promise, y) - 如果使用
reason r调用rejectPromise,以r来reject该promise - 如果
resolvePromise和rejectPromise都被调用,或者对同一参数进行多次调用,则以第一次调用为准,忽略之后的调用。 - 如果调用
then抛出了异常e如果resolvePromise或者rejectPromise已被调用,忽略- 否则,以
e作为reason来reject该promise
- 如果使用
- 如果
then不是函数,以x来fulfill该promise
- 使
- 如果
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]
