try...catch只捕获同步运行时异常,不捕获语法错误、事件回调、宏/微任务及未await的Promise拒绝;async/await中需await Promise才能使reject被catch捕获。

try...catch 不会捕获语法错误,只捕获运行时异常;异步代码(如 setTimeout、fetch)中的错误默认逃逸出 try 块,必须单独处理。
try...catch 能捕获哪些错误
它只捕获同步执行过程中抛出的 Error 实例或任意值(比如 throw "oops"),但对以下情况完全无效:
- 语法错误(如少括号、
let x = ;),这类在解析阶段就报错,根本进不了 try 块 - 事件回调里的错误(
button.addEventListener('click', () => { throw new Error(); })) - 宏任务和微任务中的错误(
setTimeout、Promise.then、queueMicrotask) - 未捕获的 Promise 拒绝(
Promise.reject()且没接.catch())
async/await 中 try...catch 的写法要点
用 async 函数包装后,await 后的 Promise 拒绝会被转为同步异常,这时 try...catch 才真正生效:
async function loadData() {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
// 这里能捕获 fetch 失败、JSON 解析失败、手动 throw 的错误
console.error('加载失败:', err.message);
}
}
- 必须
await被 reject 的 Promise,否则它只是个 pending 状态,不会触发 catch -
fetch成功返回 Response 对象不等于请求成功,res.ok和res.status需手动检查 - 不要在
await前加括号误写成await (fetch().then(...)),这会丢失错误传播链
错误对象里真正有用的信息
别只打印 err.message,很多上下文藏在其他属性里:
立即学习“Java免费学习笔记(深入)”;
-
err.name:标准错误类型名("TypeError"、"SyntaxError"—— 但注意:语法错误根本进不了 catch) -
err.stack:调用栈,含文件名和行号(开发环境有效,生产环境可能被压缩) -
err.cause(ES2022+):嵌套错误的原始原因,适合链式错误包装 - 自定义错误可添加任意字段,比如
err.code = 'NETWORK_TIMEOUT',便于分类处理
常见漏网之鱼:全局错误监听补位
对于 try...catch 顾不到的地方,得靠全局钩子兜底:
window.addEventListener('error', (e) => {
console.error('JS 错误:', e.error); // 同步错误
});
window.addEventListener('unhandledrejection', (e) => {
console.error('未处理 Promise 拒绝:', e.reason); // Promise.reject() 未被捕获
});
- 这两个监听器不能替代 try...catch,它们没有恢复执行的能力,仅用于日志和监控
-
unhandledrejection在 Promise 链末尾没写.catch()时触发,但一旦写了,就不会冒泡到这里 - Node.js 环境对应的是
process.on('uncaughtException')和process.on('unhandledRejection')
最常被忽略的是:错误处理不是“加个 try 就完事”,关键在判断哪里真需要同步捕获、哪里该用 Promise 链式处理、哪些必须交由全局监听——混用或漏掉任一环节,错误就会静默消失。











