以下代码是我的问题的MCVE:
class MyApp {
public async crash(): Promise<number> {
throw new Error("Hello Error");
}
public async chain(promise: Promise<number>) {
await this.delay(10000);
return promise;
}
private async delay(ms: number): Promise<void> {
return new Promise<void>( resolve => setTimeout(resolve, ms) );
}
}
const myApp = new MyApp();
const a = async () => {
try {
const foo = await myApp.chain(myApp.crash());
} catch (e) {
console.log("Hello Catch");
}
};
a();
我有一个Promise<>
,迟早会拒绝。我有一个处理程序,将await
表示诺言。但是,如果拒绝的速度更快,那么我的代码将导致await
调用,一些全局错误处理程序将启动并结束我的应用程序,告诉我我有一个未捕获的错误。有趣的副作用:如果我等待足够长的时间(在我的示例中为10秒),它将神奇地恢复,并记住存在一个await
和一个catch
块,并且实际上可以完成任务。
但是在那10秒钟里,我的剧本是在“我们都会死!”模式。一些全局错误处理程序启动,我的应用程序已关闭。
我在做什么错?我不是async
现在就必须处理 的全部要旨吗?为什么甚至有全局错误处理程序?
我的现实情况是这样的:
public async showWait<T>(promise: Promise<T>): Promise<T> {
await loadingSpinner.present();
try {
return await promise;
}
finally {
await loadingSpinner.dismiss();
}
}
如果执行任务的崩溃速度比显示微调器快,那么我的整个应用程序将崩溃。在您告诉我添加捕获块之前,请先查看MCVE,这不是问题。我确实从呼叫链上端的await
处捕获了异常,但是崩溃发生在之前,代码甚至到达了await
。
答案 0 :(得分:4)
问题在于,您正在构造一个承诺,但与此同时不做任何事情(未安装错误处理程序!),同时等待其他承诺:
let promise = crash();
await loadingSpinner.present();
await promise;
这是一个众所周知的反模式:Waiting for more than one concurrent await operation
通常,您的方法应接受值而不是诺言,但是在这种情况下,如果您想包装诺言,则可以保证。您仍然需要立即处理它。正确的解决方案是
public async showWait<T>(promise: Promise<T>): Promise<T> {
try {
const [, val] = await Promise.all([
loadingSpinner.present(),
promise,
]);
return val;
} finally {
await loadingSpinner.dismiss();
}
}