try catch 仅捕获同步异常,如 throw、ReferenceError、TypeError、SyntaxError;对异步错误、事件处理器错误、Promise 错误无效;需用 .catch() 或 async/await 配合;应记录 e.name 和 e.stack;finally 中抛错会覆盖原错误。

try catch 能捕获哪些错误
它只捕获**同步执行过程中抛出的异常**,比如 throw new Error()、引用未定义变量(ReferenceError)、调用非函数值(TypeError)、JSON 解析失败(SyntaxError)等。但对以下情况完全无效:
- 异步代码里的错误(如
setTimeout、Promise回调、fetch失败) - 事件处理器中抛出的错误(如
onclick里throw) - 语法错误(
SyntaxError)——这类错在解析阶段就报了,根本进不了try块
Promise 中的错误不能靠外层 try catch 捕获
写成这样是徒劳的:
try {
fetch('/api/data').then(res => res.json()).then(data => console.log(data));
} catch (e) {
console.error('这根本不会执行');
}
因为 fetch 立即返回一个 Promise,try 块结束时它还没 resolve 或 reject。正确做法是:
- 用
.catch()链式处理:fetch(...).then(...).catch(e => {...}) - 或用
async/await配合try/catch(注意函数必须是async)
async function loadData() {
try {
const res = await fetch('/api/data');
const data = await res.json();
console.log(data);
} catch (e) {
console.error('网络或解析出错了', e);
}
}
不要忽略 error 对象的细节
很多人只写 catch (e) { console.error(e) },但 e 是个对象,关键信息藏在属性里:
立即学习“Java免费学习笔记(深入)”;
-
e.message:人类可读的错误描述(如"Cannot read property 'x' of undefined") -
e.name:错误类型名("TypeError"、"SyntaxError"),可用于条件判断 -
e.stack:调用栈,定位问题位置最直接的依据 - 某些环境(如 Chrome)还提供
e.cause(链式错误原因)
生产环境建议至少记录 e.name 和 e.stack,光打 e.toString() 会丢掉上下文。
finally 不是万能收尾,别在这里 throw
finally 块总会执行,适合清理资源(如关闭加载状态、清除定时器),但它有两条铁律:
- 如果
finally里throw或返回一个 rejected Promise,它会覆盖前面try或catch中的返回值或错误 - 不要在
finally里做可能失败的操作(比如又发一次fetch),否则可能把原错误“吞掉”
常见误用:
try {
riskyOperation();
} catch (e) {
console.error(e);
throw e; // 原意是重抛
} finally {
await cleanup(); // 如果 cleanup() 抛错,上面的 throw 就被覆盖了
}
真正安全的清理,应该确保自身不抛错,或单独捕获其内部异常。











