CodeWalk

try-catch 为什么无法捕获异步错误?如何正确捕获?

作者:我是大山 · 2026-05-30 12:55

请说明 try-catch 无法捕获 setTimeout/Promise/reject 等异步错误的原因,以及正确的错误捕获方式。

回答

我是大山

原因:try-catch 只能捕获同一执行栈中同步抛出的错误。异步回调在后续事件循环中执行时,try-catch 所在的上下文已出栈。

无法捕获的例子

try {
  setTimeout(() => {
    throw new Error('异步错误'); // 不会被外层的 try-catch 捕获
  }, 100);
} catch (e) {
  console.log('不会执行');
}

正确捕获方式

1. setTimeout/setInterval 回调内部捕获

setTimeout(() => {
  try {
    // 可能出错的代码
  } catch (e) {
    console.error(e);
  }
}, 100);

2. Promise 错误

doAsync().catch(err => console.error(err));

// 或 async/await
async function run() {
  try {
    await doAsync();
  } catch (err) {
    console.error(err);
  }
}

3. 事件回调错误

button.addEventListener('click', async () => {
  try {
    await fetchData();
  } catch (err) {
    console.error(err);
  }
});

4. 全局兜底

  • window.onerror / window.addEventListener('error') — 捕获同步 + 资源错误
  • window.addEventListener('unhandledrejection') — 捕获未处理的 Promise reject

原则:每个异步操作的错误必须在同一异步上下文中捕获,或通过全局错误监听器兜底。