跳到主要内容

规范

一、认识


Promise 是对 Promises/A+ 规范的一种实现,Promises/A+规范如下:

二、术语


2.1 Promise

**Promise**是一个对象或函数,它拥有符合此规范的then方法

2.2 thenable

thenable 是一个对象或者方法,它定义了一个then方法。

2.3 value

value 是一个任意合法javascript值(可以是undefined,thenablepromise

2.4 exception

exception 是通过throw声明抛出的一个错误

2.5 reason

reason 表明了一个promise失败的原因

三、规范


3.1 Promise 状态

一个promise必须处于以下三个状态种的一种: pendingfulfilledrejected

  1. pending状态时,promise

    1. 可以转变为fulfilledrejected状态。
  2. fulfilled状态时, promise:

    1. 无法转换到其他状态
    2. 一定会包含一个value,并且无法改变
  3. rejected状态时,promise:

    1. 不能转换到其他状态
    2. 必定有reason,并且无法改变

在这里,“不能转换”意味着恒等(可以用===判断),但不适用于深层的改变(如果value或reason不为基本类型,可能会修改属性值)。

3.2 Promise 的 then 方法

promise必须提供一个then方法来访问它的当前值或最终value/reasonpromisethen方法接收2个参数值:

promise.then(onFulfilled, onRejected)
  1. onFulfilledonRejected都是可选参数:

    1. onFulfilled 如果不为函数,则会被忽略执行
    2. onRejected如果不为函数,则会被忽略执行
  2. onFulfilled如果是函数:

    1. promise变为fulfilled之后才会被调用,promisevalue会时它的第一个参数值。
    2. promise变成fulfilled之前都不会被调用。
    3. 不能被调用超过一次。
  3. onRejected如果是一个函数:

    1. 一定会在promise状态变成rejected之后调用,promisereason是它第一个参数。
    2. promise状态没有变为rejected之前不会被调用。
    3. 不能被调用超过一次
  4. onFulfilledonRejected 只有在执行环境堆栈仅包含平台代码时才可被调用

  5. onFulfilledonRejected 必须被用作函数调用

  6. then 允许在一个promise中调用多次

    1. promise状态变为fulfilled,所有onFullfilled回调必须按照初始调用then方法的先后顺序执行。
    2. promise状态变为rejected,所有onRejected回调必须按照初始调用then方法的先后顺序执行
  7. then方法必定返回一个promise

    思考

    一、为什么then方法不像jQuery那样返回this而是要重新返回一个新的promise对象

    答: 如果then返回了this,那么promise2就和promise1的状态同步,promise1状态变更后,promise2就没办法接受后面异步操作进行的状态变更,并且造成了了循环引用的问题。

3.3 Promise 解决过程

promise解决过程是一个抽象操作,它输入一个promise和一个value,我们可以表示为[[Resolve]](promise, x). 如果xthen方法且看上去像一个Promise ,解决程序即尝试使promise接受x的状态;否则其用x的值来执行promise。运行 [[Resolve]](promise, x) 需遵循以下步骤:

  1. 如果promisex指向同一个对象,使用TypeError来将promise置为rejected

    思考

    一、promise解决过程 中为什么要规定 promisex 不能指向同一对象

    答: 防止循环引用

  2. 如果xPromise ,则使promise接受x的状态

    1. 如果x处于pendingpromise 需保持为等待态直至x被执行或拒绝
    2. 如果x处于fulfiiled,用相同的值执行promise
    3. 如果x处于rejected,用相同的值拒绝promise
  3. 如果x是一个对象或函数

    1. x.then赋值给then
    2. 如果取x.then的值时抛出错误e ,则以e为据因拒绝promise
    3. 如果then是函数,将x作为函数的作用域this调用之。传递两个回调函数作为参数,第一个参数叫做resolvePromise,第二个参数叫做rejectPromise:
      1. 如果resolvePromise以值y为参数被调用,则运行[[Resolve]](promise, y)
      2. 如果rejectPromise以据因r为参数被调用,则以据因r拒绝promise
      3. 如果resolvePromiserejectPromise均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
      4. 如果调用then方法抛出了异常e
        1. 如果resolvePromiserejectPromise已经被调用,则忽略之
        2. 否则以e为据因拒绝promise
    4. 如果then不是函数,以x为参数执行promise
  4. 如果x不为对象或者函数,以x为参数执行promise

如果一个promise被一个循环的thenable链中的对象解决,而[[Resolve]](promise, thenable)的递归性质又使得其被再次调用,根据上述的算法将会陷入无限递归之中。算法虽不强制要求,但也鼓励施者检测这样的递归是否存在,若检测到存在则以一个可识别的TypeError为据因来拒绝promise

参考资料


Promise A+规范

promise探讨