try...catch 捕获异步错误

try...catch 无法捕获异步代码中的错误及解决方案

问题

try...catch 可以捕获到异步代码中的错误吗?

解答

不能。try...catch 无法捕获异步回调中抛出的错误。

以下面代码为例:

try {
  setTimeout(() => {
    throw new Error('err')
  }, 200);
} catch (err) {
  console.log(err); // 无法捕获
}

setTimeout 是一个异步函数,它的回调函数会在指定的延时后被放入事件队列,等待当前执行栈清空后才执行。因此,当 setTimeout 的回调函数执行并抛出错误时,try...catch 已经执行完毕,无法捕捉到异步回调中的错误。

对于异步代码,需要使用以下方式处理错误:

使用 Promise:

new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error('err'));
  }, 200);
}).catch(err => {
  console.log(err); // 可以捕获
});

使用 async/await:

async function handleAsync() {
  try {
    await new Promise((resolve, reject) => {
      setTimeout(() => {
        reject(new Error('err'));
      }, 200);
    });
  } catch (err) {
    console.log(err); // 可以捕获
  }
}

关键点

  • try...catch 只能捕获同步代码和当前执行栈中的错误
  • 异步回调执行时,原来的 try...catch 已经执行完毕
  • 异步错误需要使用 Promise 的 .catch()async/await 配合 try...catch 来处理
  • 也可以使用事件监听器(如 window.onerror)来捕获全局错误