Skip to content

Promise

ES6 新增加的内置类,用来处理 JS 中的异步编程问题。

  • 可以异步操作开始时或完成后,指定回调函数得到异步结果数据

  • 解决回调地狱问题

  • 可以进行链式调用

3种状态,保存在属性 [[PromiseState]] 中。

  • pending 待定

  • resolved / fulfilled 成功

  • rejected 失败

状态的 2 种变化

  • pending => resolved

  • pending => rejected

只有这两种变化,且一个 Promise 对象的状态只能改变一次,意味着变化是不可逆的。 无论成功还是失败,都会有一个结果数据,成功的结果数据一般称为 value,失败的结果数据一般 称为 reason,保存在属性 [[PromiseResult]] 中。

APIs

  • 构造函数

    new Promise ((resolve, reject) => {})

  • Promise.prototype.then(onResolved, onRejected)

    用于设置成功和失败的回调,总是返回一个新的 Promise。

    如果忽略针对某个状态的回调函数参数,或者提供非函数参数,那么 then 方法将会丢失关于 该状态的回调函数信息,但是并不会产生错误。如果 Promise 的状态发生改变,但是 then 中 并没有关于这种状态的回调函数,那么 then 将返回一个没有经过回调函数处理的新 Promise 对象,这个新 Promise 只是简单地接受调用这个 then 的原 Promise 的终态作为它的终态。

    javascript
    Promise
      .resolve(1)
      .then(2) // then 参数不是函数,返回成功的 promise,值为 1
      .then(Promise.resolve(3)) // then 参数不是函数,返回成功的 promise,值为 1
      .then(console.log) // then 参数是函数,会将 promise 的 值传给这个函数
  • Promise.prototype.catch()

    用于设置失败后执行的回调,总是返回一个新的 Promise。

  • Promise.prototype.finally()

    无论成功还是失败,最后都会执行的回调,总是返回一个新的 Promise。

  • Promise.resolve(value)

    返回一个以给定值解析后的 Promise。

    • 如果 value 是 Promise,那么直接返回这个 Promise。

      javascript
      let foo = null
      const bar = Promise.resolve(foo = new Promise((resolve, reject) => {}))
      console.log(foo === bar) // output: true
    • 如果 value 是 thenable,即 value.then 存在并且是函数,返回的 promise 会“跟随” 这个 thenable 的对象,采用它的最终状态。

      javascript
      const foo = {
        then (resolve, reject) {
          resolve('foo')
        }
      }
      Promise.resolve(foo).then(v => {
        console.log(v) // foo
      }, e => {
        console.log(e)
      })
      
      const foo = {
        then (resolve, reject) {
          throw new TypeError('error')
          resolve('foo')
        }
      }
      Promise.resolve(foo).then(v => {
        console.log(v) 
      }, e => {
        console.log(e) // TypeError: error
      })
      
      const foo = {
        then (resolve, reject) {
          resolve('foo')
          throw new TypeError('error')
        }
      }
      Promise.resolve(foo).then(v => {
        console.log(v) // foo
      }, e => {
        console.log(e)
      })
    • 如果 value 是 一个值,那么返回一个成功的 Promise,PromiseResult 就是 value。

  • Promise.reject(reason)

    返回一个失败的Promise对象

    javascript
    const p = Promise.reject(new Promise((resolve, reject) => {
      resolve('suc')
    }))
    console.log(p) // 失败,只不过失败的值是成功的 promise。
  • Promise.all(iterable)

    包含 n 个 promise 的数组,但不一定要都是 promise 对象,可以是 JS 中的任意数据类型, 如果不是 promise,默认是成功的,也会被添加进成功数据组成的数组中。

    该方法返回一个 promise,只有所有 promise 都成功了才成功,有一个失败就是失败,但是 失败了其他 promise 也会继续执行(初始化时构造器就执行了)。

    返回成功的 promise: 结果数组中数据的顺序和 promise 顺序一致 返回失败的 promise: 结果数据为第一个失败的 promise 的 reason

    javascript
    const p1 = new Promise((resolve, reject) => {
      resolve('suc1')
    })
    const p2 = Promise.resolve('suc2')
    const p3 = Promise.resolve('suc3')
    const p4 = Promise.reject('fail')
    const res = Promise.all([p1, p2, p3])
    const res2 = Promise.all([p1, p4, p3])

    如果传入的可迭代对象为空,Promise.all 会同步地返回一个已完成状态的promise。 如果所有传入的 promise 都变为完成状态,或者传入的可迭代对象内没有 promise, Promise.all 返回的 promise 异步地变为完成。

    javascript
    const p1 = Promise.resolve('p1')
    const p2 = Promise.resolve('p2')
    const p3 = Promise.reject('fail')
    const res = Promise.all([])
    const res2 = Promise.all([p1, p2, p3])
    const res3 = Promise.all(['foo', 'bar'])
    
    console.log(res) // Promise {<fulfilled>: Array(0)}
    console.log(res2) // Promise {<pending>}
    console.log(res3) // Promise {<pending>}
    
    setTimeout(() => {
      console.log('@')
      console.log(res2) // Promise {<rejected>: 'fail'}
      console.log(res3) // Promise {<fulfilled>: Array(2)}
    }, 0);
  • Promise.race(iterable)

    返回一个 pedding 状态的 promise,当迭代中出现第一个改变状态的 promise 时,异步的 返回的 promise 的状态,并将值设为第一个改变状态的 promise 的值。如果 iterable 为 空数组,返回的 promise 将是 pending 状态,如果 iterable 没有改变状态的 promise 或 没有 promise,异步的修改返回的 promise 状态为 resolved,值是第一个非 promise 数据类型的值。

    javascript
    const p1 = new Promise(function(resolve, reject) {
      setTimeout(resolve, 500, "one");
    });
    const p2 = new Promise(function(resolve, reject) {
      setTimeout(resolve, 100, "two");
    });
    
    Promise.race([p1, p2]).then(function(value) {
      console.log(value); // "two" 两个都完成,但 p2 更快
      
    });
  • Promise.allSettled(iterable)

    返回一个在所有给定的 promise 都已经 fulfilled 或 rejected 后的 promise,状态总是 成功,值是一个数组,里面的每个对象表示对应的 promise 状态和结果。

    javascript
    const p1 = Promise.reject('foo')
    const p2 = Promise.resolve('bar')
    const p3 = Promise.reject('baz')
    const res = Promise.allSettled([p1, p2, p3])
    // PromiseResult
    // [
    //   {status: 'rejected', reason: 'foo'},
    //   {status: 'fulfilled', value: 'bar'},
    //   {status: 'rejected', reason: 'baz'}
    // ]
  • Promise.any(iterable)

    返回一个新的 promise,一旦可迭代对象内的任意一个 promise 变成了成功状态,那么返回的 promise 就会变成成功状态,并且它的值就是第一个变成成功的 promise 的值。如果可迭代对 象内的 promise 最终都没有成功(即所有 promise 都失败了),那么该方法所返回的 promise 就会变成失败状态,并且它的值是 AggregateError 实例,这是 Error 的子类, 用于把单一的错误集合在一起。如果只有失败和待定的 promise,返回的 promise 状态就是 pending,如果只有失败和除 promise 外的数据值,返回成功的 promise 且值就是第一个 数据值。

    javascript
    const p1 = Promise.reject('foo')
    const p2 = Promise.resolve('bar')
    const p3 = Promise.reject('baz')
    const res = Promise.any([p1, p2, p3])