最近在排查项目问题,发现部分日志奇怪丢失,明明外部有try catch 包裹。这里记录一下排查过程及解决方案。
宏任务异常
async function cb() {
return new Promise((resolve, reject) => {
reject('err') // 只能通过 promise.catch 捕获
reject(new Error('err')) // 可以捕获
// throw new Error('err') 与上面代码效果相同
})
}
async function foo() {
try {
cb()
// await cb() 加 await 则可以捕获
} catch (error) {
console.log('myError', error.message)
}
}
foo()
原因:async 函数是 generate 函数的语法糖。根据 await 将函数拆分成几段异步调用链。及await 后面的代码是等到cb 的promise.then 中执行。如果没有 await 就是同步执行。cb 函数的错误没有被捕获。
**
微任务异步异常
async function foo() {
try {
setTimeout(() => {
throw new Error('err')
}, 1000)
} catch (error) {
console.log('myError', error.message)
}
}
foo() // 没有任何错误打印
原因: foo() 函数退出了调用栈(try,catch 也执行完)。之后setTimeout 回调执行,此时没有异常捕获
解决方案
- 在异步函数内部 try catch
- 外部包裹 async await 函数,try catch 捕获(例如 koa 中间件进行异常捕获,不要忘记 await next())
- 监听 process
uncaughtException
,unhandledRejection
事件