最近在排查项目问题,发现部分日志奇怪丢失,明明外部有try catch 包裹。这里记录一下排查过程及解决方案。

宏任务异常

  1. async function cb() {
  2. return new Promise((resolve, reject) => {
  3. reject('err') // 只能通过 promise.catch 捕获
  4. reject(new Error('err')) // 可以捕获
  5. // throw new Error('err') 与上面代码效果相同
  6. })
  7. }
  8. async function foo() {
  9. try {
  10. cb()
  11. // await cb() 加 await 则可以捕获
  12. } catch (error) {
  13. console.log('myError', error.message)
  14. }
  15. }
  16. foo()

原因:async 函数是 generate 函数的语法糖。根据 await 将函数拆分成几段异步调用链。及await 后面的代码是等到cb 的promise.then 中执行。如果没有 await 就是同步执行。cb 函数的错误没有被捕获。
**

微任务异步异常

  1. async function foo() {
  2. try {
  3. setTimeout(() => {
  4. throw new Error('err')
  5. }, 1000)
  6. } catch (error) {
  7. console.log('myError', error.message)
  8. }
  9. }
  10. foo() // 没有任何错误打印

原因: foo() 函数退出了调用栈(try,catch 也执行完)。之后setTimeout 回调执行,此时没有异常捕获

解决方案

  1. 在异步函数内部 try catch
  2. 外部包裹 async await 函数,try catch 捕获(例如 koa 中间件进行异常捕获,不要忘记 await next())
  3. 监听 process uncaughtException , unhandledRejection 事件