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

Uncaught Exception with async constructor pattern

这个class有点特别,因为它在构造函数中使用了很多异步调用,而构造函数不能是异步的,所以我使用了一种我在互联网上读到的特殊模式:

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函数会出现异常,所以我模拟了这个情况。目前,我收到以下错误:

Uncaught (in promise): [object Undefined]

在控制台中我看到:

reject

undefined

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

问题是您在 instantiate 中使用了 async。使 async 成为可能的机制将创建另一个 Promise 来包装 Promise 你 return 并且这个承诺实际上不会捕获它的异常(因为你没有捕获构造函数中的错误)

最简单的解决方案是删除 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);
});

或者使用 async 并且不需要使用 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);
});