try...catch仅捕获同步运行时错误,对语法错误、异步错误(setTimeout/Promise/事件回调)、fetch网络失败(未手动throw)均无效;Promise错误需用.catch()或await+try...catch;全局错误需window.onerror、error事件及unhandledrejection监听。

try...catch 只能捕获同步运行时错误
它对语法错误、异步错误(如 setTimeout 或 Promise 中抛出的异常)、事件回调里的错误、fetch 网络失败(除非你手动 throw)都无能为力。常见误解是以为加了 try...catch 就万事大吉,其实它只管当前执行栈里“立刻跑起来”的那部分代码。
比如下面这段不会被捕获:
try {
setTimeout(() => {
throw new Error('这个错 catch 不到');
}, 0);
} catch (e) {
console.log('永远不会执行这里');
}
原因:setTimeout 的回调在新任务中执行,已脱离原始 try 块的作用域。
Promise 错误必须用 .catch() 或 await 配合 try...catch
Promise 构造函数内部抛错,不会触发外层 try...catch;但用 await 调用时,可以被包裹它的 try...catch 捕获——前提是没漏掉 await 关键字。
立即学习“Java免费学习笔记(深入)”;
- 写法正确(可捕获):
async function fetchUser() { try { const res = await fetch('/api/user'); if (!res.ok) throw new Error(`HTTP ${res.status}`); return await res.json(); } catch (err) { console.error('请求或解析失败:', err.message); } } - 写法错误(不可捕获):
function badExample() { try { fetch('/api/user').then(r => r.json()).catch(e => console.error(e)); // 这里没 await,fetch 是立即返回 Promise,try 块早就结束了 } catch (e) { // 永远进不来 } }
全局错误兜底:用 window.onerror 和 window.addEventListener('error')
它们能捕获未被处理的 JS 错误、资源加载失败(如 )、甚至部分跨域脚本错误(受浏览器策略限制)。但注意:window.onerror 无法拿到 error 实例的完整堆栈(尤其跨域时),而 error 事件监听器更通用些。
推荐组合使用:
window.onerror = function(message, source, lineno, colno, error) {
console.warn('onerror:', { message, source, lineno, colno, error: error?.stack });
return true; // 阻止默认错误提示(可选)
};
window.addEventListener('error', function(e) {
if (e.error) {
console.warn('Error event with error object:', e.error.stack);
} else if (e.target && e.target.src) {
console.warn('Resource load failed:', e.target.src);
}
});
注意:Promise 拒绝未被捕获时,会触发 unhandledrejection 事件,别忘了加监听:
window.addEventListener('unhandledrejection', e => {
console.warn('Unhandled Promise rejection:', e.reason);
e.preventDefault(); // 阻止控制台警告(谨慎使用)
});
实际项目中容易忽略的点
很多团队只加了 try...catch 就以为覆盖全面了,结果线上 still crash。真正要稳住,得盯住这几处:
- 所有
JSON.parse()必须包try...catch—— 它是典型的同步运行时错误源,且常出现在响应体解析环节 - 第三方 SDK 的回调(如微信 JS-SDK、地图 API)多数不走 Promise,错误靠传参或事件,不能依赖
await -
addEventListener里的 handler 函数,错误不会冒泡到外层try,需各自加保护 - Vue/React 组件的生命周期或渲染函数出错,会被框架捕获并降级(如 Vue 的
errorCaptured钩子),但自定义逻辑仍要主动防御
错误处理不是加一层 try...catch 就结束的事,关键在判断错误发生的位置和时机——同步?异步?是否在 Promise 链里?有没有跨执行上下文?漏掉任意一种,就可能变成静默失败或白屏。











