在ES7中,我们将为JS提供async
和await
关键字。它对于常规功能看起来很有希望。但是我们如何在异步事件中处理异常呢?
例如
async badFunc()
{
throw "bad";
}
var reader = new FileReader();
reader.onload = async function ()
{
await badFunc();
}
根据我的理解,async
函数将是一个语法糖,它将使用Promise
的resolve
和reject
功能。因此,只有在调用者使用await
关键字时才会捕获异常。
在上面的示例中,await badFunc();
行将捕获异常并重新抛出它。但由于onload
处理程序可能没有在回调上调用await
,因此异常将在空白中丢失。甚至window.onerror
也无法抓住它。
所以我的问题是。在事件中使用等待的正确方法应该是什么,以便异常不会丢失?
你是对的,async-await只是承诺的语法糖。任何异步函数都会返回在函数返回时解析的Promise
,或者在函数抛出异常时被拒绝。
async foo() {
return 1;
}
const promise1 = foo(); // here we have a promise that will resolve in 1
async bar() {
throw new Error('something went wrong');
}
const promise2 = bar(); // here we have a promise that will be rejected with an error.
这些承诺可以像任何常规承诺一样处理,例如:
foo().then(…).catch(…);
在异步函数内部,您可以使用await关键字。如果后面是promise(或类似promise的对象),它将暂停执行异步函数并等待promise的解析。如果promise解析,其结果将用作表达式的结果。如果它被拒绝,将在使用await的行上抛出异常。
例:
const promise3 = async baz() {
const boo = await foo(); // (1)
const zoo = await bar(); // (2)
}
(1)暂停此线并等待承诺解决;承诺结束后,嘘声变得相等1。
(2)暂停此线并等待承诺解决;承诺拒绝后,抛出异常。
可以使用try ... catch捕获await抛出的错误。如果他们不是,他们将冒泡,这意味着promise3
将被拒绝。
async badFunc()
{
throw "bad";
}
var reader = new FileReader();
reader.onload = function ()
{
(async()=>{
await badFunc();
})().then(()=>()).catch(e=>console.log(e))
}
我已经用调用内部异步IIFE的普通事件处理程序替换了异步事件处理程序。 console.log(e)
可以替换为您觉得有用的任何错误例程。
请注意,您可以通过在末尾放置一个'return x
'来从处理程序返回一个标准值 - 这将始终在评估badFunc的Promise之前触发,即使它被拒绝。除非您的回调期望并且将评估Promise返回值,否则您无法根据内部承诺的已解决状态返回值。你可以链接到另一个事件监听器。
此外,虽然window.onerror
不会发现错误,但unhandledrejection
将在Chrome和其他一些浏览器中捕获它。 Firefox显然不会。这对于调试代码来说足够好,但是不能在生产中捕获任何东西。