try…catch仅捕获同步运行时错误,如throw、JSON.parse失败、undefined调用等;异步、Promise拒绝、资源加载错误需用async/await、.catch()、window.onerror或window.onunhandledrejection处理。

JavaScript 错误不能靠 try…catch 全部捕获,它只抓同步代码里的运行时错误;异步、全局、资源加载类错误得另想办法。
哪些错误能被 try…catch 捕获
try…catch 只拦截当前执行栈中抛出的同步异常,比如:
throw new Error('oops')JSON.parse('{invalid}')-
undefined.foo()(TypeError) -
require('missing-module')(Node.js 中的同步 require 失败)
但以下情况完全无效:
-
setTimeout(() => { throw new Error('gone') }, 0)—— 异步回调脱离当前 try 块 -
fetch('/api').then(r => r.json())—— Promise 拒绝不会进 catch 块(除非显式.catch()或await后不加try) -
加载失败 —— 属于资源错误,触发window.onerror
try…catch 必须配合 finally 和具体 error 类型判断
只写 catch (e) { console.log(e) } 很危险:你不知道它是不是真该被吞掉,还是该上报或重试。
立即学习“Java免费学习笔记(深入)”;
建议写法:
try {
const data = JSON.parse(input);
processData(data);
} catch (err) {
if (err instanceof SyntaxError) {
console.warn('JSON 格式错误,跳过处理', input);
return null;
}
if (err instanceof TypeError) {
console.error('数据结构异常', err);
throw err; // 不是语法问题,就继续上抛
}
throw err; // 兜底,不意外吞掉未知错误
} finally {
cleanup(); // 清理资源,无论成功失败都执行
}
注意:catch 参数名用 err 比 e 更明确;finally 不要放可能抛错的逻辑,否则会掩盖原错误。
异步代码怎么用 try…catch
只有 async/await 能让 try…catch 生效,Promise 链不行。
- ✅ 正确:
try { const res = await fetch('/api'); const json = await res.json(); } - ❌ 无效:
fetch('/api').then(r => r.json()).catch(...)—— 这个catch是 Promise 方法,和外层try无关
常见坑:
-
await后忘了加try…catch,错误直接 unhandled rejection - 多个
await写在一行里(如await foo(); await bar();),第二个失败时第一个的副作用已发生,需考虑回滚 -
Promise.all([a(), b()])中任一拒绝就会进catch,但你拿不到哪个先失败 —— 改用Promise.allSettled更可控
全局错误不能只靠 try…catch,还得配 window.onerror 和 window.onunhandledrejection
浏览器中,漏掉的错误主要在这两类:
-
window.onerror:捕获脚本语法错误、资源加载失败、同步运行时错误(未被任何try包裹的) -
window.onunhandledrejection:捕获没被.catch()或try…await处理的 Promise 拒绝
示例注册:
window.onerror = function(msg, url, line, col, error) {
console.error('全局 JS 错误', { msg, url, line, col, stack: error?.stack });
reportError({ type: 'js-error', msg, stack: error?.stack });
};
window.onunhandledrejection = function(event) {
console.error('未捕获 Promise 拒绝', event.reason);
reportError({ type: 'promise-reject', reason: event.reason });
};
注意:window.onerror 的 error 参数在跨域脚本中可能为空(因安全限制),此时只能靠 msg 和 url 猜;onunhandledrejection 的 event.reason 才是真实错误对象,别只打 event。
真正难处理的是微任务队列中的错误(比如 queueMicrotask(() => { throw 1 })),它既不进 try…catch,也不触发 onunhandledrejection,目前没有标准捕获方式 —— 尽量别这么写。











