Promise/A+ 规范主要是针对 then 方法,将来的工作可能会拓展到如何创建 fullfill、reject promise 这些方面
Promise 状态
- 内部实现只有 3 种状态:pending、fullfilled、rejected
- state 为 pending 状态时,可以赋值为 fullfilled 或者 rejected 状态
- state 为 fullfilled / rejected 时
- promise 不能再赋值为其它状态
- promise 一定要有不能改变的 value / reason 值 不能再改变
then 方法
promise 必须提供 then 方法来访问最终 value 值或者 reason:
promise.then(onFullfilled, onRejected)
- onFullfilled、onRejected 都是可选的参数
- 如果它们不是函数,可以忽略下面的逻辑处理了
- 如果 onFullfilled 是函数
- 只有当 state 为 fullfilled 时才能调用 onFullfilled 函数,value 是它的第一个参数
- promise 为 fullfilled 前都不能调用
- 只能调用一次 onFullfilled
- 如果 onRejected 是函数
- 同上,对应的状态为 rejected,以及对应的 value 参数改为 reason
- onFullfilled、onRejected 只有在执行上下文栈执行以下逻辑时才调用 // 延时绑定的实现
- 它们是异步执行的,只有在调用then 任务的时候,它们才异步执行的
- 可以通过宏任务 setTimeout / setImmediate 或者 微任务 MutationObserver / process.nextTick 来实现这个异步操作
- onFullfilled、onRejected 只能当作函数调用,不能使用 this 值。// 因为 this 指向不明,strict 模式下,this 指向 undefined;非 strict 模式下,this 指向 window 全局对象
- then 可能会在一个 promise 上执行多次
- fullfilled 时,onFullfilled 回调函数执行时机必须跟它们相对应的 then 方法顺序一致
- rejected 时,同上
- then 必须返回一个 promise // 值穿透
promise2 = promise1.then(onFulfilled, onRejected);- 如果 onFullfilled、onRejected 返回的是一个普通值 x,执行以下 Promise Resolution Procedure
Resolve(promise, x) - 如果 onFullfilled、onRejected 抛出 exception e,统一使用 e 作为错误原因
- 如果 onFullfilled 不是函数且 promise1 为 fullfilled 时,promise2 也一定是 fullfilled 且 value 值跟 promise fullfilled 的 value 值一样
- 如果 onRejected 不是函数且 promise1 为 rejected,promise2 也一定为 rejected且值 reason 同 promise1 一样
- 如果 onFullfilled、onRejected 返回的是一个普通值 x,执行以下 Promise Resolution Procedure
promise resolution procedure
是一个抽象操作,它使用 promise 和 x 作为参数,可以记作为:function Resolve(promise, x) 。如果 x 是一个 thenable 对象,它会使得 promise 跟 x 的状态是一样的,当然前提是 x 表现得像个 promise 一样,否则它会让 promise 的 fullfilled 得到的 value 值为 x
Resolve(promise, x) 执行如下步骤
-
如果 promise、x 引用同一个对象,则 promise reject,以 TypeError 作为 reason
-
如果 x 为 promise,考虑以下几种状态
- 如果 x state 为 pending,则 promise 会一直为 pending 状态,直到 x 状态为 fullfilled 或者 rejected
- 当 x state 为 fullfilled,promise 也为 fullfill 状态,且它们有相同的 value 值
- 当 x state 为 rejected,promise 也为 reject 状态,且它们有相同的 reason
-
当 x 是一个对象或者函数时
-
让 then = x.then
-
如果 x.then 报错,抛出 e 错误,则 promise rejected 且以 e 为 reason
-
如果 then 是函数。使用 x 来调用它,x 充当 this 角色,第一个参数为 resolvePromise,第2个参数为 rejectPromise。即:
then.call(x, resolvePromise, rejectPromise)- 当 resolvePromise 传入 y 来调用时,即:Resolve(promise, y)
- 当 rejectPromise 传入 r 来调用时,promise reject 时需要使用 r 作为参数
- 如果 resolvePromise、rejectPromise 都调用了,或者多次使用相同参数来调用,则优先第1次调用,其余的调用都可以忽略了
- 如果 then 抛出异常 e
- 如果 resolvePromise 或者 rejectPromise 任一调用了,则可以忽略这次异常
- 否则 promise reject 使用 e 作为 reason
-
x不是函数或者对象时,promise fullfill 需要使用 x 传参
-