try-catch仅捕获同步运行时异常,对语法错误、异步错误、Promise拒绝等无效;需在async函数中用await配合try-catch,或用.catch()处理Promise,语法错误须依赖编辑器/构建工具检测。
JavaScript 中的错误处理核心就是 try-catch,但它不是万能的“兜底开关”——它只捕获同步代码中抛出的异常,对异步错误、语法错误、Promise 拒绝(reject)或未捕获的 Promise 错误默认不生效。
try-catch 有效?它只在运行时同步执行路径中起作用。比如调用一个会抛出 throw new Error() 的函数,或访问 undefined 的属性(TypeError),或 JSON.parse() 解析失败(SyntaxError)。
常见误区是以为它能捕获 setTimeout 或 fetch 里的错误——其实不能,除非你在回调或 async 函数内部自己写 try-catch。
try 块里必须是可立即执行的同步语句catch 参数(如 err)是 Error 实例,有 message、name、stack 等属性finally 总会执行,适合清理资源(如关闭模拟连接、重置状态),但不要在里面 return 或抛错,否则会覆盖前面的返回值或异常try {
JSON.parse('{ "valid": true'); // 缺少 }
} catch (err) {
console.log(err.name); // SyntaxError
console.log(err.message); // "Unexpected end of JSON input"
}
try-catch 对 Promise 错误无效?直接包住 fetch() 或 new Promise() 不会捕获其内部拒绝(reject)。因为 Promise 构造器本身同步执行,但 reject 是异步调度的,脱离了 try 块的执行栈。
正确做法是:在 async 函数中用 await,再套 try-catch;或用 .catch() 显式处理 Promise 链。
await + try-catch 更直观,但只在 async 函数内可用.catch() 更通用,适用于任何 Promise,包括非 async 上下文Uncaught (in promise) ... 控制台警告,甚至被全局 unhandledrejection 事件捕获
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) {
console.error('加载失败:', err.message);
return null;
}
}
try-catch 根本捕不到?语法错误(SyntaxError)在代码解析阶段就报错,根本不会进入执行,所以 try-catch 完全无效。同理,模块加载失败(如 import 路径错误)、顶层 await 报错、或 eval 外部的语法问题,都不归它管。
另外,异步任务中的未处理拒绝(Promise.reject() 没接 .catch)、资源加载失败(如 的 onerror)、或 postMessage 通信错误,也都需要各自对应的机制处理。
window.addEventListener('unhandledrejection', ...)
img.onerror、script.onerror 等原生事件真正难的不是写 try-catch,而是判断该在哪一层加、加了是否真起作用、以及有没有漏掉异步分支或边界条件。很多线上静默失败,都是因为把 try-catch 当成了“全局异常保险丝”,而没意识到它的作用域非常具体。