前几天遇到一个问题:想捕获异步函数的错误,但是捕获不到。我的代码大概是这样:
try {
(async () => {
// 一大堆异步函数
})();
} catch (e) {
if (e.message.startsWith('my error:') {
// 我的错误,提示一下即可
} else {
// 某种不知名错误,继续抛出
throw new Error(e.message);
}
}
不知道读者是否发现问题,我当时是左看右看没看出来。后来只好写最小用例缩小问题范围,终于找到问题所在:异步函数前面缺少 await
。于是想通了,上面的代码其实被引擎解释成:
try
一个函数- 这个函数的返回值是一个 Promise
- Promise 是正常对象,所以
try
成功 - 至于 Promise 里的函数是否失败,不关
try
的事,所以自然捕获不到
所以正确的写法是:
// 外面先套一层,不然不能用 await
(async () => {
try {
// 再加上 `await`
await (async () => {
// 异步函数体
})();
} catch (e) {
// ....
}
})();
这个 await
至关重要。这是异步函数的一大特性,即 try...catch
可以捕获整个异步操作前后所有栈的异常,而不仅仅是当前函数的异常。同时我们也要注意,异步函数的调用可能并不在当前栈,也无法被 try...catch
在当前栈捕获到错误。
欢迎吐槽,共同进步