最近在看Nodejs
方面的内容,突然想到了Promise
,于是想到看看它的标准,手搓一个出来。
这是一篇长文,准备分段更新。
目录
1. 标准
更新日志:2019年1月21日
完成了标准部分的内容。
标准
先从标准入手,下文为标准的翻译。
术语
Promise
对象/函数拥有then
方法,其行为符合本规范thenable
表明一个对象/函数拥有then
方法value
是一个合法的JavaScript
值,包括undefined
,thenable
和promise
exception
是通过throw
抛出的value
reason
是一个用来表示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
必须返回一个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)
要执行如下步骤:
- 如果
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]