JavaScript错误处理靠try...catch、throw和监控机制实现可响应,仅捕获运行时异常,不捕获语法错误或未处理的Promise拒绝;Promise错误需用.catch()或await+try...catch捕获;应按错误类型分类处理,全局监听仅作兜底。
JavaScript 的错误处理不是靠“写得完美”来避免问题,而是靠 try...catch、throw 和恰当的监控机制把不可控变成可响应。
try...catch?它只捕获**运行时异常(runtime errors)**,比如访问 undefined 的属性、JSON 解析失败、fetch 返回 404 后手动 response.json() 失败等。它不捕获语法错误、Promise 拒绝(unhandled rejection)、或异步回调里的同步错误(除非你在回调里自己包一层)。
JSON.parse() 输入不可信、调用第三方 SDK 方法但文档没写清边界条件
await 导致后续逻辑基于 Promise 对象运行try...catch 有轻微性能开销,不要包裹整个函数体或高频循环;只包真正可能抛错的最小代码块Promise 链中的错误怎么捕获?Promise 构造器内部抛出的错误会被自动转为拒绝状态,但必须用 .catch() 或 await 配合 try...catch 捕获——不能靠外层 try...catch 包住 new Promise(...) 就完事。
常见错误写法:
try {
new Promise((resolve, reject) => {
throw new Error('boom'); // 这个错误不会被外层 try 捕获
});
} catch (e) {
console.log(e); // 永远不会执行
}
正确做法是:
.catch(): fetch('/api').then(r => r.json()).catch(err => {...})
async/await 时,在 await 行外层套 try...catch:因为 await 会把 rejected Promise 转成同步抛错Promise.allSettled() 而非 Promise.all(),避免一个失败就中断全部原生 JS 错误类型如 SyntaxError、TypeError、ReferenceError 可以直接用 instanceof 判断;自定义错误建议继承 Error 并设 name 字段,方便分类。
示例:
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
try {
throw new ValidationError('用户名不能为空');
} catch (err) {
if (err instanceof ValidationError) {
showFormError(err.message);
} else if (err.name === 'TypeError') {
logToSentry(err);
}
}
err.message 做判断——字符串易变、多语言下不可靠fetch 的 network error、HTTP 状态码、业务 code 分层处理err.stack 是非标准字段,但所有主流环境都支持;若需跨平台兼容,不要把它当核心逻辑依赖try...catch 吗?不能。全局钩子如 window.onerror、window.addEventListener('error')、process.on('uncaughtException')(Node.js)只作为兜底,用于日志收集和降级,无法阻止错误传播或恢复现场。
window.onerror 捕获脚本加载错误、全局同步错误,但不捕获 Promise 拒绝(需 unhandledrejection)unhandledrejection 里 event.preventDefault() 可阻止控制台报错提示,但不推荐——掩盖问题比记录更危险try...catch 或 .catch()
最常被忽略的是:异步操作中错误上下文丢失。比如在 setTimeout 或事件回调里抛错,堆栈里看不到原始调用链——这时候靠 error.stack 不够,得结合 console.trace() 或异步追踪库(如 cls-hooked)补全。