Promise API及实现

83 阅读16分钟

一、Promise的使用

1. 什么是Promise

PromiseES6提供的构造函数,Promise对象用来表示一个异步操作的最终状态(成功或失败),以及该异步操作的结果值。

Promise对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理回调函数,这使得异步方法可以像同步方法那样返回,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的Promise对象。

Promise对象可以解决异步嵌套问题以及多个异步并发问题,但Promise依旧是基于回调的写法,在复杂业务逻辑下可能还会存在嵌套问题,而且无法终止异步。

通过genertor函数+co库处理Promise异步,可以解决回调嵌套问题,简化then的使用。终极解决方案是ES7中提供的genertor函数+co库的语法糖async-await

2. Promise对象的内部属性

  • [[PromiseStatus]] : 内部变量, 存储Promise对象当前的状态值。
  • [[PromiseResult]]: 内部变量,存储失败或成功的结果。
[[PromiseStatus]]状态值含义
pending初始状态,既不是成功,也不是失败状态。
fulfilled意味着操作成功完成; 调用resolve函数可以将状态扭转至fulfilled
rejected意味着操作失败;调用reject函数或者抛出异常可以将状态扭转至rejected
[[PromiseStatus]]的状态改变后,不能再次被修改。

3. 创建Promise对象

通过new关键字调用Promise构造函数创建一个实例时,需要为构造函数传入一个executor执行器函数,该函数是同步执行的,并且执行时会接收两个参数分别是resolve函数及reject函数。

执行resolve函数可以将Primise对象的状态改为fulfilled成功态,调用resolve函数时传入的参数是Promise对象的成功结果。

执行reject函数可以将Primise对象的状态改为rejected失败态,reject函数的入参是Promise对象的失败结果。

function exector (resolve, reject) {
    
}
console.log(new Promise(exector)); 
// Promise {<pending>}
// [[prototype]]: Promise
// [[PromiseStatus]]: pending
// [[PromiseResult]]: undefined

4. executor执行器函数

executor函数

executor函数是创建Promise对象时的入参,executor函数由程序员定义,在new Promise(executor)时是会立即同步调用传入的executor函数,并且调用时会传递两个参数分别是resolve函数及reject函数。

resolve

Promise内部定义, 但由程序员手动调用的函数。

当异步任务成功时,我们应该调用resolve函数,resolve函数被调用,内部会同步修改Promise对象的状态,将其置为fulfilled以及将传入的参数作为成功结果保存,然后异步执行所有onResolved回调函数。

reject

Promise内部定义,当异步任务失败或抛出error时,我们应该调用reject函数, reject函数被调用,内部会同步修改Promise对象的状态,将其置为rejected并将传入的参数作为失败的原因保存,然后异步调用所有onRejected回调函数。

注意:一个失败的Promise必须要进行捕获即必须要由onRejected回调函数处理错误,否则会报错

5. Promise常用API

Promise.prototype.then([onResolved] [, onRejected])

then()方法是Promise原型中的方法,该方法可以接受两个可选参数,分别是Promise的状态为处理异步成功或异步失败的回调函数,当Promise对象的状态改变时会异步执行对应状态的回调函数。

then()方法的返回值是一个新的Promise对象,也正是因为返回值是一个Promise对象,因此可以实现链式调用。其返回的Promise对象的状态由回调函数如何执行决定:

  • onResolvedonRejected回调函数正常执行,且回调函数的返回值是一个Promise对象,则会立即执行该Promise对象,并且将该Promise对象的状态及结果值作为then()方法返回的Promise对象状态及结果
  • onResolvedonRejected回调函数正常执行,则返回的Promise对象为成功态,且回调函数的返回值为Promise对象的成功结果;
  • onResolvedonRejected回调函数抛出异常,则返回的Promise对象为失败态,且抛出的错误为Promise对象的失败原因。
// 当回调函数中的返回值为Promise对象时,then方法的返回的Promise对象的状态及值,取决于回调中返回的Promise的状态及值
const p = new Promise((res, rej) => {
    setTimeout(() => {res(1)}, 1000)
})
p.then(() => {
    return Promise.reject('e');;
}).then((v) => {
    console.log('fulfilled:' , v);
}, (e) => {
    console.log('rejected:' , e);
})
扩展:

基于then()的返回值取决于其回调的返回值的特点,可以实现通过在回调中返回一个始终为pending状态的Promise对象终止Promise.prototype.then方法的链式调用。

Promise.resolve().then(() => {
    return new Promise(() => {}); // 终止promise
})
Promise.prototype.catch(onRejected])

catch()方法时then()方法的语法糖,相当于then(null, onRejected)

Promise.prototype.finally(onFinally) (ES9提供)

当一个Promise的状态确定后,无论是fulfilled还是rejectedonFinally回调都会执行。

finally()方法返回一个新的Promise对象,若onFinally回调中抛出错误或返回一个失败的Promise,则finally()方法返回的Promise对象的状态为rejected并取其失败原因,否则新的Promise对象与当前执行finally()方法的Promise对象状态保持一致。

new Promise((resolve, reject) => {
    reject(1)
}).finally(() => {
    console.log('onFinally执行');
}).catch((e) => {
    console.log('onRjected执行:', e);
})

// 输出结果:
// onFinally执行
// onRjected执行:1
Promise.resolve(value)

Promise.resolve()Promise构造函数的静态方法,返回一个确定状态Promise对象。

Promise.resolve()用于包装普通值时,是手动创建一个fulfilled状态的Promise对象的快捷方法;Promise.resolve()接收Promise对象时,无论是否是嵌套的Promise都将其展开执行,最终返回一个有状态的Promise对象。

但返回的Promise对象最终状态及值取决于传入的参数:

  • 若参数时Promise,则将传入的Promise的执行,并将最终状态及结果值作为返回的Promise对象的状态及结果;
  • 若为其它值,则为返回的Promise对象的成功结果。
Promise.reject(reason)

Promise.reject()Promise构造函数的静态方法,始终返回一个失败的Promise对象,是手动创建一个rejected状态的Promise对象的快捷方法。

无论参数reason是不是Promise对象,都不会等待执行该Promise对象。直接将接收的Promise对象作为失败原因。

Promise.all(iterable)

Promise.all()Promise提供的静态方法,接收的参数iterable是一个可迭代对象,常为数组类型,返回值是一个新的Promise对象。

Promise.all()用于处理多个异步并发请求,只有当所有异步都成功,其返回的Promise对象才是成功态,成功的结果组成的数组与iterable中的顺序一致;任何一个异步失败则立即返回失败态的Promise对象。

const p1 = new Promise((res) => {
    setTimeout(() => res(1), 1000);
})
const p2 = Promise.resolve(2);
Promise.all([p1, 3, p2]).then (d => {
    console.log(d);
})

Promise.all('aoi').then((d) => {
    console.log(d);
})
// 输出结果:
// [ 'a', 'o', 'i' ]
// [ 1, 3, 2 ]
Promise.rate(iterable)

Promise.rate()方法是Promise提供的静态方法,其接收的参数和返回值同Promise.all()方法一致。

Promise.rate()方法将参数iterable中第一个得到结果的状态及结果值作为返回的Promise对象的状态和结果。

Promise.allSettled(iterable)

Promise.allSettled()方法是Promise提供的静态方法,其接收的参数和同Promise.all()方法一致,接受一个可迭代对象,返回一个成功状态的Promise对象。

无论iterable中是否存在失败的PromisePromise.allSettled()方法始终后返回一个成功的Promise对象。其成功的结果为一个数组,数组中的元素是一个对象,每个对象都包含以下属性:

  • status:表示该下标的Promise对象的最终状态,值为fulfilledrejected
  • value:当状态为fulfilled时,才存在该属性,其值为成功的结果。
  • reason:当状态为rejected时,才存在该属性,其值为失败的原因。
const p1 = new Promise((res) => {
    setTimeout(res(1), 1000)
})
const p2 = Promise.reject('a');
const p3 = new Promise((res, rej) => {
    setTimeout(() => {
        if (Math.random() > 0.5) res(100);
        else rej(1000)
    }, 1000)
})

Promise.allSettled([p1, p2, p3]).then((data) => {
    console.log('data:', data)
}, err => console.log('err: ', err))

// 输出结果
// data: [
//   { status: 'fulfilled', value: 1 },
//   { status: 'rejected', reason: 'a' },
//   { status: 'fulfilled', value: 100 }
// ]

二、Promise源码实现

源码规定详见 Promise A+规范 可以通过promises-aplus-tests库来校验自己实现的Promise是否符合规范。

1. 简易同步版Promise实现

Promise实例的内部属性PromiseStatus存放状态,初始状态为pending,状态一经改变后不能再次改变;

Promise实例的内部属性PromiseResult存放成功的结果或失败的原因;

执行new Promise(executor)时会立即同步调用传入的executor函数,并且调用时会传递两个参数分别是resolve函数及reject函数;

resolve执行将状态改为成功态,并将参数作为成功结果;reject执行或者抛出异常则将状态改为失败态,并将参数/异常作为失败原因;

then()方法中的回调函数会在状态为fulfilledrejected时执行对应的回调函数。

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class Promise {
    constructor (executor) {
        this.PromiseStatus = PENDING;
        this.PromiseResult = undefined;

        let resolve = (value) => { // 为了拿到this,应使用箭头函数
            if (this.PromiseStatus === PENDING) {
                this.PromiseStatus = FULFILLED;
                this.PromiseResult = value;
            }
        }

        let reject = (reason) => {
            if (this.PromiseStatus === PENDING) {
                this.PromiseStatus = REJECTED;
                this.PromiseResult = reason;
            }
        }

        // 抛出异常则将状态改为失败态,并将异常结果作为失败原因
        try {
            executor (resolve, reject);
        } catch (e) {
            reject(e);
        }
    }

    then (onFulfilled, onRejected) {
        if (this.PromiseStatus === FULFILLED) {
            onFulfilled(this.PromiseResult)
        }
        if (this.PromiseStatus === REJECTED) {
            onRejected(this.PromiseResult)
        }
    }
}

module.exports = Promise;
2. 基于发布订阅模式处理异步情况
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class Promise {
    constructor (executor) {
        this.PromiseStatus = PENDING;
        this.PromiseResult = undefined;

        // 存放异步回调
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];

        let resolve = (value) => {
            if (this.PromiseStatus === PENDING) {
                this.PromiseStatus = FULFILLED;
                this.PromiseResult = value;
                // 发布
                this.onFulfilledCallbacks.forEach(fn => fn())
            }
        }

        let reject = (reason) => {
            if (this.PromiseStatus === PENDING) {
                this.PromiseStatus = REJECTED;
                this.PromiseResult = reason;
                // 发布
                this.onRejectedCallbacks.forEach(fn => fn())
            }
        }

        // 抛出异常则将状态改为失败态,并将异常结果作为失败原因
        try {
            executor (resolve, reject);
        } catch (e) {
            reject(e);
        }
    }

    then (onFulfilled, onRejected) {
        // 同步处理
        if (this.PromiseStatus === FULFILLED) {
            onFulfilled(this.PromiseResult)
        }
        if (this.PromiseStatus === REJECTED) {
            onRejected(this.PromiseResult)
        }
        // 异步处理
        if (this.PromiseStatus === PENDING) {
            // 订阅
            this.onFulfilledCallbacks.push(() => {
                // 切片思想, todo something...
                onFulfilled(this.PromiseResult)
            });
            this.onRejectedCallbacks.push(() => {
                onRejected(this.PromiseResult)
            });
        }
    }
}

module.exports = Promise;
3. 实现then()方法的链式调用

then()方法的返回值是一个新的Promise对象,也正是因为返回值是一个Promise对象,因此可以实现链式调用。其返回的Promise对象的状态由回调函数如何执行决定:

  • onResolvedonRejected回调函数正常执行,且回调函数的返回值是一个Promise对象,则会立即执行该Promise对象,并且将该Promise对象的状态及结果值作为then()方法返回的Promise对象状态及结果;
  • onResolvedonRejected回调函数正常执行,则返回的Promise对象为成功态,且回调函数的返回值为Promise对象的成功结果;
  • onResolvedonRejected回调函数抛出异常,则返回的Promise对象为失败态,且抛出的错误为Promise对象的失败原因。
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

// resolvePromise方法用来解析then方法回调的返回值x,并且处理then方法的返回值promise2的状态及结果
const resolvePromise = function (promise2, x, resolve, reject) {
    // 1. 防止出现let promise2 = Promise.resolve().then(() => promise2)循环引用死循环,直接抛出错误
    if (promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
    }
    // 2. promise规范规定,promise可以是一个对象或者函数,因此此方法需要兼容所有promise
    if (Object.prototype.toString.call(x) === '[object Object]' || typeof x === 'function') {
        /* 若x是由外部实现的promise,别人的then方法可能会多次执行会回调或then内部抛出,需要一个标识变量防止resolve、reject多次执行
            const x = {
                then (onFulfilled, onRejected) {
                    onFulfilled();
                    onFulfilled();
                    onRejected();
                    throw new Error();
                }
            }
        */
        let called = false;
        /* 防止取then属性报错,或执行then时报错,应捕获其错误,一旦抛出异常则立即失败
            const x = {}; 
            Object.defineProperty(x, then, {
                get () {
                    throw new Error();
                }
            })
        */
        try { 
            /* x是别人定义的promise,且可能被defineProperty定义特殊处理过,多次取then报错,为了增加代码的容错性,提前取出保存。
                const x = {}; 
                let time = 2;
                Object.defineProperty(x, then, {
                    get () {
                        if (--time === 0) {
                            throw new Error();
                        }
                    }
                })
            */
            let then = x.then; 
            // x有then属性,且值是一个函数,则将其视为一个promise对象
            if (typeof then === 'function') {
                then.call(x, y => { // 使用call,而不是直接使用x.then(),同样也是防止多次取then报错
                    // 若已经改变了状态,拒绝继续执行
                    if (called) return;
                    called = true;
                    // 为了防止y还是一个promise,应进行递归处理,如果y不是一个promise,递归后会进入3.直接转为成功
                    resolvePromise(promise2, y, resolve, reject);
                }, e => {
                    if (called) return;
                    called = true;
                    reject(e);
                })
            }
        } catch (e) {
            if (called) return;
            called = true;
            reject(e);
        }

    } else { 
        // 3. x是一个普通值,直接转为成功并将返回值x作为成功结果
        resolve(x);
    }

}

class Promise {
    constructor (executor) {
        this.PromiseStatus = PENDING;
        this.PromiseResult = undefined;

        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];

        let resolve = (value) => {
            if (this.PromiseStatus === PENDING) {
                this.PromiseStatus = FULFILLED;
                this.PromiseResult = value;
                this.onFulfilledCallbacks.forEach(fn => fn())
            }
        }

        let reject = (reason) => {
            if (this.PromiseStatus === PENDING) {
                this.PromiseStatus = REJECTED;
                this.PromiseResult = reason;
                this.onRejectedCallbacks.forEach(fn => fn())
            }
        }

        try {
            executor (resolve, reject);
        } catch (e) {
            reject(e);
        }
    }

    then (onFulfilled, onRejected) {
        // then方法返回一个Promise对象
        let promise2 = new Promise((resolve, reject) => { // executor同步执行
            if (this.PromiseStatus === FULFILLED) {
                // 由于executor同步执行,要等待executor执行完毕,new Promise才能返回promise2,因此需要通过异步等待promise2创建成功
                process.nextTick(() => { // Promise采用微任务异步等待promise2
                    // 回调中抛出异常,则then返回一个失败的promise
                    try {
                        let x = onFulfilled(this.PromiseResult);
                        // 解析返回值
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                })
            }
            if (this.PromiseStatus === REJECTED) {
                process.nextTick (() => {
                    try {
                        let x = onRejected(this.PromiseResult)
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                })
            }
            if (this.PromiseStatus === PENDING) {
                this.onFulfilledCallbacks.push(() => { 
                    process.nextTick (() => {
                        try {
                            let x = onFulfilled(this.PromiseResult)
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    })
                });
                this.onRejectedCallbacks.push(() => {
                    process.nextTick (() => {
                        try {
                            let x = onRejected(this.PromiseResult)
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    })
                });
            }
        })
        return promise2;
    }
}

module.exports = Promise;
4. 实现then()方法值的穿透
class Promise {
    then (onFulfilled, onRejected) {
        // then方法可选参数处理,如果未传递onFulfilled/onRejected回调函数,则将成功或失败的结果向后传递
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : data => data;
        onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error };
    }
}
5. 实现deferred延迟方法

实现deferred延迟方法为了符合Promise A+规范,若不存在延迟方法,测试过程中会提示TypeError: adapter.deferred is not a function.错误。该方法在原生javaScirpt中的Promise是没有被实现的。

// 延迟对象,返回一个对象,该对象中保存了一个promise对象及其resolve和reject方法
Promise.deferred = function () {
    let dfd = {};
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    })
    return dfd;
}
deferred延迟方法可以用于减少将异步操作封装成Promise对象时回调的嵌套,因此在一些类库中也有实现。
const fs = require('fs');

// 将fs.read方法包装成promise
function read (url) {
    return new Promise((resolve, reject) => { // 嵌套
        fs.readFile(url, 'utf-8', (err, data) => {
            if (err) reject(err);
            else resolve(data);
        })
    })
}

// 实现defer方法
function defer () {
    const dfd = {};
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    })
    return dfd;
}
// 使用延迟对象减少promise嵌套
function read1 (url) {
    const dfd = defer();
    fs.readFile(url, 'utf-8', (err, data) => {
        if (err) dfd.reject(err);
        else dfd.resolve(data);
    })
    return dfd;
}
6. catch()方法的实现

catch()方法是then()方法的语法糖,等同于then(null, onRejected)

class Promise {
    catch (onRejected) {
        return this.then(null, onRejected);
    }
}
7. Promise.all(iterable)方法的实现

Promise.all()Promise提供的静态方法,接收的参数iterable是一个可迭代对象,常为数组类型,返回值是一个新的Promise对象。

Promise.all()用于处理多个异步并发请求,只有当所有异步都成功,其返回的Promise对象才是成功态,成功的结果组成的数组与iterable中的顺序一致;任何一个异步失败则立即返回失败态的Promise对象。

// 判断是否为promise对象
const isPromise = function (val) {
    if (Object.prototype.toString.call(val) === '[object Object]' || typeof val === 'function') {
        if (typeof val.then === 'function') return true;
    }
    return false;
}

class Promise {
    static all (iterable) {
        return new Promise ((resolve, reject) => {
            const res = []; // 存放结果
            let count = 0;  // 由于存在异步,因此需要计数器统计全部得到值后再改变成功状态
            const len = iterable.length;

            // 保存成功结果,并计数等待所有异步有结果后将状态置为成功
            function saveData(k, v) {
                res[k] = v;
                if (++count === len) { // 计数
                    resolve(res)
                }
            }

            for (let i = 0; i < len; i++) {
                const val = iterable[i];
                // 若是一个promise,则立即执行并等待其状态及结果,若为普通值则立即保存其值
                if (isPromise(val)) {
                    val.then(v => {
                        saveData(i, v);
                    }, reject); // 一旦异步失败,则all方法立即失败
                } else {
                    saveData(i, val);
                }
            }
        })
    }
}
8. Promise.resolve(value)方法的实现

Promise.resolve()Promise构造函数的静态方法,返回一个确定状态Promise对象。

Promise.resolve()用于包装普通值时,是手动创建一个fulfilled状态的Promise对象的快捷方法;Promise.resolve()接收Promise对象时,无论是否是嵌套的Promise都将其展开执行,最终返回一个有状态的Promise对象。

但返回的Promise对象最终状态及值取决于传入的参数:

  • 若参数时Promise,则将传入的Promise的执行,并将最终状态及结果值作为返回的Promise对象的状态及结果;
  • 若为其它值,则为返回的Promise对象的成功结果。
class Promise {
   constuctor (executor) {
        let resolve = (value) => {
            // 若调用Promise.resolve()方法传入一个promise对象,应执行传入的promise对象,并获取到其值作为Promise.resolve()返回值的状态及结果
            if (value instanceof Promise) {
                return value.then(resolve, reject); // 递归解析promise
            }

            if (this.PromiseStatus === PENDING) {
                this.PromiseStatus = FULFILLED;
                this.PromiseResult = value;
                // 发布
                this.onFulfilledCallbacks.forEach(fn => fn())
            }
        }
   }
   
   static resolve (value) {
        return new Promise ((resolve, reject) => {
            resolve(value);
        })
    }
}
9. Promise.reject(reason)方法的实现

Promise.reject()Promise构造函数的静态方法,始终返回一个失败的Promise对象,是手动创建一个rejected状态的Promise对象的快捷方法。

class Promise {
     static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason);
        });
    }
}
10. Promise.race(iterable)方法的实现

race()方法是Promise提供的静态方法,其返回值是一个Promise对象。其状态和结果取决于iterable中第一个确定状态结果的Promise对象。

class Promise {
    static race (iterable) {
        return new Promise((resolve, reject) => {
            iterable.forEach((value) => {
                // 最先确定状态的promise对象决定race方法返回的promise对象的状态及结果
                Promise.resolve(value).then(resolve, reject);
            });
        });
    }
}
11. Promie.prototype.allSettled(iterable)方法的实现

无论iterable中是否存在失败的PromisePromise.allSettled()方法始终后返回一个成功的Promise对象。其成功的结果为一个数组,数组中的元素是一个对象,每个对象都包含以下属性:

  • status:表示该下标的Promise对象的最终状态,值为fulfilledrejected
  • value:当状态为fulfilled时,才存在该属性,其值为成功的结果。
  • reason:当状态为rejected时,才存在该属性,其值为失败的原因。
class Promsie {
    static allSettled (iterable) {
        return new Promise ((resolve) => {
            const data = [];
            const list = [...iterable];
            let len = list.length;

            list.forEach((item, index) => {
                Promise.resolve(item).then((v) => {
                    // 保存成功的结果
                    data[index] = {
                        status: 'fulfilled',
                        value: v
                    }
                    // 计数,当所有的promise都有结果后将返回的promise对象置为成功态
                    if (--len === 0) {
                        resolve(data);
                    }
                }, e => {
                    // 保存失败的结果
                    data[index] = {
                        status: 'rejected',
                        reason: e
                    }
                    if (--len === 0) {
                        resolve(data);
                    }
                })
            })
        })
    }
}
12. Promise.prototype.finally(onFinally)方法的实现

当一个Promise的状态确定后,无论是fulfilled还是rejectedonFinally回调都会执行。

finally()方法返回一个新的Promise对象,若onFinally回调中抛出错误或返回一个失败的Promise,则finally()方法返回的Promise对象的状态为rejected及其原因,否则finally()方法返回新Promise对象与当前执行finally()方法的Promise对象状态保持一致。

class Promise {
    finally (onFinally) {
        // 无论成功或失败onFinally都会执行, 因此在then的成功和失败中都执行
        return this.then (data => {
            // onFinally可能会返回一个promise对象,因此可以使用Promise.resolve(),来解析onFinally的返回值
            // 如果返回失败的promise或抛出错误,则采取onFinally的失败及其原因;除此以外onFinally不会影响原先的值的状态(即采用之前的状态和值)
            Promise.resolve(onFinally()).then(() => value, e => { throw e });
        }, err => {
            // 基于当前Promise对象的失败状态或onFinally返回的失败状态
            return Promise.resolve(onFinally()).then(() => { throw err }, e => { throw e });
        })
    }
}