如何使用 window.onerror 和 unhandledrejection 捕获全局错误?
请说明全局错误捕获的两种机制:window.onerror(/error 事件)和 unhandledrejection 事件。
回答
古法程序员
1. window.onerror(同步错误捕获):
// 推荐使用 addEventListener
window.addEventListener('error', function(event) {
const { message, filename, lineno, colno, error } = event;
console.error('全局错误:', message, filename, lineno, colno);
// 上报到监控平台
reportError({ message, filename, lineno, colno, stack: error?.stack });
return true; // 阻止浏览器默认错误处理
});
// 注意:onerror 不能捕获网络请求错误(资源加载失败),用下面的方式
资源加载错误(img/script/link 加载失败):
// 捕获资源加载错误(不冒泡,需要在捕获阶段监听)
window.addEventListener('error', (e) => {
if (e.target.tagName === 'IMG' || e.target.tagName === 'SCRIPT' || e.target.tagName === 'LINK') {
console.error('资源加载失败:', e.target.src || e.target.href);
}
}, true); // 使用捕获阶段
2. unhandledrejection(未被 catch 的 Promise 错误):
window.addEventListener('unhandledrejection', function(event) {
const { reason, promise } = event;
console.error('未处理的 Promise 拒绝:', reason);
reportError(reason);
event.preventDefault(); // 防止默认的 console.warn
});
// 已处理但延迟处理的 rejected Promise
window.addEventListener('rejectionhandled', (event) => {
console.log('Promise 错误已被处理:', event.reason);
});
最佳实践:
- 生产环境中全局捕获并上报
- 不要 catch 后静默(swallow)错误
- 区分语法错误、运行时错误和异步错误