Skip to content

Promise ​

Promise 是异步编程的一种解决方案。简单的说就是一个容器,里面保存着一个异步操作的结果。 Promise 是一个对象,他可以获取异步操作的消息。有以下特点:

  • 对象的状态不受外界影响,Promise 对象代表一个异步操作,有三种状态:pending(仅限进行中),fulfilled(已成功),rejected(已失败)。
  • 一旦状态改变就不会再变,任何时候都可以得到这个结果。状态改变只能是从 pending 到 fulfilled 和 pending 到 rejected。

缺点:

  • 一旦新建就无法取消
  • 如果不设置回调函数 Promise 内部抛出的错误不会反应到外部
  • 当处于 pending 状态是无法知道进展到哪一个阶段

基本用法 ​

Promise 对象是一个构造函数,用来生成 Promise 实例

var promise = new Promise(function(resolve, reject) {
    // ... some code
    if (/* 异步操作成功 */){
        resolve(value);
    } else {
        reject(error);
    }
});

promise.then(function(value) {
    // success
}, function(error) {
    // failure
});

Promise 构造函数接受一个函数作为参数,该函数有两个参数 resolve 和 reject。resolve 函数的作用是将 Promise 对象的状态从 pending 变为 resolved,在异步操作成功的时候将结果传递出去。 reject 函数的作用是将 Promise 对象的状态从 pending 变为 rejected,在失败时调用并将结果作为参数传递出去。 Promise 实例生效后可以用 then 方法分别指定 resolved 的状态和 rejected 状态的回调函数。

Promise.prototype.then() ​

then 方法是定义在原型对象 Promise.prototype 上的。它的作用是为 Promise 实例添加状态改变时的回调函数。then 方法返回的是一个新的 Promise 实例,因此可是采用链式的写法,即在 then 后再加拎一个 then 方法

Promise.prototype.catch() ​

Promise.prototype.catch 方法是.then(null, rejection)的别名,用于指定发生错误时的回调。如果 then 方法指定的回调函数运行中抛出异常也会被 catch 方法捕获。 如果 Promise 状态已经变成 resolved,再抛出错误是无效的。

Promise.all() ​

将多个 Promise 实例包装成一个新的 Promise 实例

var p = Promise.all([p1, p2, p3])

Promise.all 方法接受一个数组作为参数(可以不是数组但必须具有 Iterator 接口),每个元素都是 Promise 实例,如果不是会调用 Promise.resolve 方法,将参数转为 Promise 实例 p 的状态由 p1, p2, p3 决定:

  • 只有 p1, p2, p3 状态都变为 fulfilled,p 的状态才会变为 fulfilled,此时 p1, p2, p3 的返回值组成一个数组传递给回调函数
  • 只要 p1, p2, p3 之中一个被 rejected,p 的状态就变为 rejected,此时第一个被 reject 的实例的返回值会传给 p 的回调函数

Promise.race() ​

同样是将多个 Promise 实例包装成一个新的 Promise 实例。不同的是只要有一个先改变状态,新 Promise 的状态就会跟着改变。

Promise.resolve() ​

将现有的对象转为 Promise 对象

Promise.reject() ​

返回一个新的 Promise 实例,状态为 rejected

两个有用的附加方法 ​

ES6 的 Promise API 提供的方法不是很多,有些有用的方法可以自己部署。下面介 绍如何部署两个不在 ES6 之中、但很有用的方法。

  • done()

    Promise 对象的回调链不管以 then 结尾还是 catch 结尾,只要最后一个方法抛出异常都可能无法捕捉。因此提供一个 done 方法总是处于回调的尾端保证抛出任何可能的错误。

Promise.prototype.done = function (onFulfilled, onRejected) {
    this.then(onFulfilled, onRejected)
        .catch(function (reason) {
            // 抛出一个全局错误
            setTimeout(() => { throw reason }, 0);
    });
};
  • finally()

    不管 Promise 对象最后的状态如何都会执行。

Promise.prototype.finally = function (callback) {
    let P = this.constructor;
    return this.then(
        value => P.resolve(callback()).then(() => value),
        reason => P.resolve(callback()).then(() => { throw reason })
    );
};