具有异步构造函数模式的未捕获异常

时间:2018-08-14 07:25:21

标签: typescript exception-handling promise

该类有点特殊,因为它在构造函数中使用了许多异步调用,并且构造函数不能异步,所以我使用了一种在互联网上了解的特殊模式:

export class MapLayer {
    public Ready: Promise<any>;

    constructor() {
        this.instantiate();
    }

    async instantiate(): Promise<void> {
        return this.Ready = new Promise((resolve, reject) => {
            this.parseServiceDefiniton().then(() => {
               // ...
               resolve(undefined);
            }).catch((ex) => {
                console.log('reject');
                reject();
            });
        });
    }

    async parseServiceDefiniton(): Promise<boolean> {
        throw Error('test');
    }

}

我如何使用它:

const lyr: MapLayer =  new MapLayer ();

     lyr.Ready.then(() => {


    }).catch(ex => {
       console.log(ex);
    });

由于parseServiceDefiniton函数中可能发生异常,因此我正在模拟这种情况。目前,我收到以下错误消息:

  

未捕获(承诺):[object undefined]

在控制台中,我看到:

  

拒绝

     

未定义

我看不到我没有在哪里捕捉异常!

1 个答案:

答案 0 :(得分:1)

问题是您在async内使用了instantiate。使async成为可能的机制将创建另一个Promise,该包裹将包裹您返回的Promise,并且此诺言实际上不会捕获到异常(因为您没有捕获到错误中的错误)构造函数)

最简单的解决方案是删除async。由于您不需要在体内使用await,因此实际上不需要async

export class MapLayer {
    public Ready!: Promise<any>;

    constructor() {
        this.instantiate();
    }

    instantiate(): Promise<void> {
        return this.Ready = new Promise((resolve, reject) => {
            this.parseServiceDefiniton().then(() => {
                // ...
                resolve(undefined);
            }).catch((ex) => {
                console.log('reject');
                reject(ex);
            });
        });
    }

    async parseServiceDefiniton(): Promise<boolean> {
        throw Error('test');
    }

}

const lyr: MapLayer = new MapLayer();

lyr.Ready.then(() => {
}).catch(ex => {
    console.log(ex);
});

或者是使用异步版本且不需要使用Promise构造函数的版本:

export class MapLayer {
    public Ready!: Promise<any>;

    constructor() {
        this.Ready = this.instantiate();
    }

    async instantiate(): Promise<void> {
        try {
            await this.parseServiceDefiniton()
        } catch (ex) {
            console.log('reject');
            throw ex;
        }
    }

    async parseServiceDefiniton(): Promise<boolean> {
        throw Error('test');
    }

}

const lyr: MapLayer = new MapLayer();

lyr.Ready.then(() => {
}).catch(ex => {
    console.log(ex);
});