javascript全局异步异常统一上报的核心是监听error和unhandledrejection事件,封装reporterror函数结构化采集上下文信息,并通过sendbeacon或fetch上报;同时支持主动上报、采样控制与用户标识注入。

JavaScript 中实现全局异步异常统一上报埋点,核心是捕获所有未被显式处理的 Promise 拒绝(unhandledrejection)和未捕获错误(error),再结合可扩展的上报机制,把上下文信息(如 URL、时间、堆栈、用户标识等)结构化发送到监控服务。
监听 unhandledrejection 和 error 事件
这是最基础也是最关键的两处入口:
-
window.addEventListener('error'):捕获同步执行错误、资源加载失败(如 script、img)、以及部分跨域脚本错误(注意:跨域脚本的error事件中event.error.stack通常为空,只能拿到event.filename和event.lineno) -
window.addEventListener('unhandledrejection'):捕获未被.catch()或try/catch await处理的 Promise 拒绝。注意:该事件的event.reason可能是 Error 实例,也可能是原始值(如字符串、数字),需兼容处理
封装统一的异常上报函数
避免重复逻辑,把采集、格式化、上报抽成一个函数,例如:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function reportError({ type, error, message, filename, lineno, colno, url, timestamp = Date.now() }) {
const payload = {
type, // 'js-error' | 'promise-reject'
url: window.location.href,
userAgent: navigator.userAgent,
timestamp,
message: message || (error && error.message) || String(error),
stack: (error && error.stack) || '',
filename: filename || (error && error.filename) || '',
lineno: lineno || (error && error.lineno) || 0,
colno: colno || (error && error.colno) || 0,
// 可选:添加用户/会话标识
uid: localStorage.getItem('uid') || '',
sid: sessionStorage.getItem('sid') || ''
};
// 使用 navigator.sendBeacon 确保页面卸载前也能发出(推荐)
if (navigator.sendBeacon) {
const blob = new Blob([JSON.stringify(payload)], { type: 'application/json' });
navigator.sendBeacon('/api/log/error', blob);
} else {
// 回退用 fetch(注意:页面关闭时可能被浏览器取消)
fetch('/api/log/error', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
keepalive: true // 部分浏览器支持,辅助页面卸载时发送
});
}
}
增强上下文与可控性
仅靠全局事件不够精准,建议补充以下能力:
-
主动上报支持:暴露
window.$reportError(error, extra)方法,供业务代码在已知异常分支中手动调用(比如 API 响应异常但未 throw) -
采样控制:高流量站点需避免全量上报,可在上报前加简单采样逻辑(如
Math.random() ) - 错误去重:对相同错误消息 + 堆栈 hash 在短时间内(如 60s)做节流,防止刷屏上报
-
资源加载错误细化:监听
<script></script>、<img>的onerror,并打上资源类型标签,便于定位 CDN 或构建问题
注意事项与避坑点
实际落地时容易忽略的关键细节:
- 跨域脚本错误堆栈受限 → 启用
crossorigin="anonymous"并确保服务端返回Access-Control-Allow-Origin,才能拿到完整 stack -
unhandledrejection默认会触发 console warning → 可在监听后调用event.preventDefault()抑制(但不推荐完全屏蔽,开发环境应保留提示) - Vue/React 等框架有自己的错误边界(
errorBoundary、componentDidCatch)→ 需单独集成,不能只依赖全局事件 - 不要在上报逻辑里 throw 新错误,否则可能造成二次异常循环
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










