window.onerror 和 window.addeventlistener('unhandledrejection') 分别捕获同步错误和未处理 promise 拒绝,二者互补覆盖多数异常,但无法捕获 console.error、网络请求失败及绕过监听的第三方脚本,需结合框架错误边界与采样脱敏等策略完善监控。

在 JavaScript 中,window.onerror 和 window.addEventListener('unhandledrejection') 是捕获前端异常的两个核心全局监听机制,分别用于捕获同步脚本错误和未处理的 Promise 拒绝。它们不能替代 try-catch,但能兜住漏网之鱼,是前端监控和错误上报的关键入口。
用 error 事件捕获 JS 运行时错误
window.onerror 是最常用的全局错误监听方式,能捕获脚本执行中发生的同步错误(如语法错误、引用错误、类型错误),以及资源加载失败(如 img、script 标签 404)。
- 它接收 5 个参数:
message(错误信息)、source(出错脚本 URL)、lineno(行号)、colno(列号)、error(Error 实例,包含堆栈) - 必须返回
true才能阻止错误冒泡到控制台(一般不建议阻止,仅用于特殊场景) - 注意:它无法捕获 Promise 内部抛出但未被 catch 的错误(这类归
unhandledrejection管)
示例:
window.onerror = function(message, source, lineno, colno, error) {
console.log('JS 错误:', {
message,
source,
lineno,
colno,
stack: error?.stack
});
// 上报错误数据(如发请求到监控服务)
return false; // 不阻止默认行为(保留控制台输出)
};
用 unhandledrejection 捕获未处理的 Promise 拒绝
Promise 被 reject 但没有对应 .catch() 或 await 后无 try-catch 时,会触发 unhandledrejection 事件。这是捕获异步错误的必备手段。
- 事件对象有
reason(拒绝原因,通常是 Error 实例或任意值)和promise(被拒绝的 Promise 实例) - 若在事件回调中对
reason做了处理(比如记录日志),浏览器就不会再抛出 “Uncaught (in promise)” 警告 - 注意:它只监听“未被处理”的 rejection;一旦 Promise 链中有
.catch()或顶层 await 被 try-catch 包裹,就不会触发
示例:
window.addEventListener('unhandledrejection', event => {
console.log('未捕获的 Promise 错误:', {
reason: event.reason,
promise: event.promise
});
// 上报错误(尤其注意 reason 可能不是 Error 实例,需判断)
if (event.reason instanceof Error) {
// 正常上报 stack、message 等
} else {
// 处理非 Error 类型的 reject(如 reject('timeout'))
}
});
组合使用 + 注意事项
两者互补,合起来可覆盖绝大多数运行时异常场景,但仍有局限:
- 不能捕获
console.error主动打印的内容,也不能捕获网络请求失败(需配合fetch/XMLHttpRequest自行拦截) - 第三方 SDK 或动态插入的 script 可能绕过监听(尤其是内联 script 或 document.write 注入)
- Vue/React 等框架有自己的错误边界(Error Boundary / errorCaptured),应在框架层优先处理,再交由全局监听兜底
- 生产环境上报前建议加采样(如 10% 上报)、脱敏(过滤用户敏感字段)、防抖(避免连续错误刷屏上报)
推荐初始化顺序和最小实践
为确保监听器尽早生效,建议在 HTML 最顶部的 script 中注册:
<script>
// 先监听 unhandledrejection(避免 Promise 初始化阶段漏掉)
window.addEventListener('unhandledrejection', e => {
e.preventDefault(); // 阻止默认警告(可选)
reportError({ type: 'unhandledrejection', reason: e.reason });
});
// 再设置 onerror(注意:赋值方式比 addEventListener 更可靠兼容旧版 IE)
window.onerror = (msg, url, line, col, err) => {
reportError({ type: 'error', msg, url, line, col, stack: err?.stack });
};
function reportError(data) {
// 实际上报逻辑:fetch('/log', { method: 'POST', body: JSON.stringify(data) })
}
</script>Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











