记一个 `try…catch` 异步函数的坑
前几天遇到一个问题:想捕获异步函数的错误,但是捕获不到。我的代码大概是这样:
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 在当前栈捕获到错误。
相关文章
聊聊错误/异常处理
又是繁忙的一周。突然发现以前没聊过错误/异常处理,准备分享一下。 这里我就不细究错误(Error)/异常(Ex […]
2024-11-107 分钟
使用 `postMessage` 跨域名迁移 `localStorage`
朋友的网站有个需求:要从 A 域名迁移到 B 域名。所有内容不变,只是更改域名。这个需求不复杂,理论上改下配置 […]
2023-02-127 分钟
在 Code.fun 做 Code Review(三):聊聊 Promise 的错误处理、如何真正学到技术
嗯,不知不知觉这个系列写到第三篇,这一篇会改变一下写法,从一次 Code Review 出发,讲解几个技术点, […]
2022-08-2110 分钟


