规范
一、认识
Promise
是对 Promises/A+
规范的一种实现,Promises/A+
规范如下:
二、术语
2.1 Promise
**Promise
**是一个对象或函数,它拥有符合此规范的then方法
2.2 thenable
thenable
是一个对象或者方法,它定义了一个then
方法。
2.3 value
value
是一个任意合法javascript
值(可以是undefined
,thenable
或promise
)
2.4 exception
exception
是通过throw
声明抛出的一个错误
2.5 reason
reason
表明了一个promise
失败的原因
三、规范
3.1 Promise 状态
一个promise必须处于以下三个状态种的一种: pending,fulfilled或rejected
-
在pending状态时,promise:
- 可以转变为fulfilled或rejected状态。
-
当fulfilled状态时, promise:
- 无法转换到其他状态
- 一定会包含一个value,并且无法改变
-
当rejected状态时,promise:
- 不能转换到其他状态
- 必定有reason,并且无法改变
在这里,“不能转换”意味着恒等(可以用===判断),但不适用于深层的改变(如果value或reason不为基本类型,可能会修改属性值)。
3.2 Promise 的 then 方法
promise必须提供一个then方法来访问它的当前值或最终value/reason
。promise的then方法接收2个参数值:
promise.then(onFulfilled, onRejected)
-
onFulfilled和onRejected都是可选参数:
- onFulfilled 如果不为函数,则会被忽略执行
- onRejected如果不为函数,则会被忽略执行
-
onFulfilled如果是函数:
- 在promise变为fulfilled之后才会被调用,promise的value会时它的第一个参数值。
- 在promise变成fulfilled之前都不会被调用。
- 不能被调用超过一次。
-
onRejected如果是一个函数:
- 一定会在promise状态变成rejected之后调用,promise的reason是它第一个参数。
- 在promise状态没有变为rejected之前不会被调用。
- 不能被调用超过一次
-
onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用
-
onFulfilled 和 onRejected 必须被用作函数调用
-
then 允许在一个promise中调用多次
- 当promise状态变为fulfilled,所有onFullfilled回调必须按照初始调用then方法的先后顺序执行。
- 当promise状态变为rejected,所有onRejected回调必须按照初始调用then方法的先后顺序执行
-
then方法必定返回一个promise
思考一、为什么
then
方法不像jQuery
那样返回this
而是要重新返回一个新的promise
对象答: 如果
then
返回了this
,那么promise2
就和promise1
的状态同步,promise1
状态变更后,promise2
就没办法接受后面异步操作进行的状态变更,并且造成了了循环引用的问题。
3.3 Promise 解决过程
promise解决过程是一个抽象操作,它输入一个promise和一个value,我们可以表示为[[Resolve]](promise, x)
. 如果x有then方法且看上去像一个Promise ,解决程序即尝试使promise接受x的状态;否则其用x的值来执行promise。运行 [[Resolve]](promise, x)
需遵循以下步骤:
-
如果promise和x指向同一个对象,使用TypeError来将promise置为rejected。
思考一、
promise
解决过程 中为什么要规定promise
和x
不能指向同一对象答: 防止循环引用
-
如果x为Promise ,则使promise接受x的状态
- 如果x处于pending, promise 需保持为等待态直至x被执行或拒绝
- 如果x处于fulfiiled,用相同的值执行promise
- 如果x处于rejected,用相同的值拒绝promise
-
如果x是一个对象或函数
- 把x.then赋值给then
- 如果取x.then的值时抛出错误e ,则以e为据因拒绝promise
- 如果then是函数,将x作为函数的作用域this调用之。传递两个回调函数作为参数,第一个参数叫做resolvePromise,第二个参数叫做rejectPromise:
- 如果resolvePromise以值y为参数被调用,则运行
[[Resolve]](promise, y)
- 如果rejectPromise以据因r为参数被调用,则以据因r拒绝promise
- 如果resolvePromise和rejectPromise均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
- 如果调用then方法抛出了异常e:
- 如果resolvePromise或rejectPromise已经被调用,则忽略之
- 否则以e为据因拒绝promise
- 如果resolvePromise以值y为参数被调用,则运行
- 如果then不是函数,以x为参数执行promise
-
如果x不为对象或者函数,以x为参数执行promise
如果一个promise被一个循环的thenable链中的对象解决,而[[Resolve]](promise, thenable)
的递归性质又使得其被再次调用,根据上述的算法将会陷入无限递归之中。算法虽不强制要求,但也鼓励施者检测这样的递归是否存在,若检测到存在则以一个可识别的TypeError为据因来拒绝promise