done() 和 finally()

done()

Promise对象的回调链,不管以then方法或catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(因为Promise内部的错误不会冒泡到全局)。因此,我们可以提供一个done方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。

asyncFunc()
  .then(f1)
  .catch(r1)
  .then(f2)
  .done();

示例 :

var p1 = new Promise(function(resolve, reject){
    setTimeout(()=>{
        resolve(1);
    }, 1000);
});
var p2 = new Promise(function(resolve, reject){
    setTimeout(()=>{
        reject("error 0001");
    }, 500);
});
let p = Promise.all([p1,p2]);
Promise.prototype.done = function (onFulfilled, onRejected) {
    this.then(onFulfilled, onRejected)
    .catch(function (reason) {
        // 抛出一个全局错误
        throw reason;
    });
};
p.then(function(res){
    console.log(res);
}).catch(function(e){
    console.log(e);
});

从上面代码可见,done方法的使用,可以像then方法那样用,提供Fulfilled和Rejected状态的回调函数,也可以不提供任何参数。但不管怎样,done都会捕捉到任何可能出现的错误,并向全局抛出。

finally()

finally方法用于指定不管Promise对象最后状态如何,都会执行的操作。它与done方法的最大区别,它接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。

var p1 = new Promise(function(resolve, reject){
    setTimeout(()=>{
        resolve(1)
    }, 1000);
});
var p2 = new Promise(function(resolve, reject){
    setTimeout(()=>{
        resolve(2)
    }, 500);
});

let p = Promise.all([p1,p2]);
p.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};
p.then(function(res){
    console.log(res);
}).catch(function(e){
    console.log(e);
}).finally(function(){
    console.log("finally");
});