onerror重复上报导致错误率虚高,根本原因是同一错误在单页内被多次捕获;需基于error.stack指纹限频去重,并统一处理onerror、document.error、unhandledrejection三源错误,同时保留关键路径错误的原样上报能力。

onerror 重复上报会导致错误率虚高、告警失真,根本原因是同一错误在单页内被多次捕获——比如滚动加载图片时连续触发 5 次 404,或 Promise 拒绝后又抛出 unhandledrejection。
为什么 window.onerror 会重复触发
它不区分错误来源和上下文:一个 Cannot read property 'data' of null 可能在组件 mount、render、effect 里各报一次;fetch 失败后重试逻辑若没加锁,每次失败都进 window.onerror。浏览器不会自动去重,也不管你是不是已经处理过这个堆栈。
- 错误堆栈(
error.stack)是去重最可靠的依据,比error.message更稳定(同个错误 message 可能因变量值不同而变化) -
unhandledrejection的e.reason?.stack必须显式提取,直接用e.stack是 undefined - 资源加载错误(如
<img>、<script></script>)的event.target.src+ 错误类型可作为辅助指纹,但不能单独依赖
按错误指纹限频:5 秒内相同堆栈只报 1 次
用 Map 缓存最近报错的堆栈哈希,超时自动清理。哈希生成要简单高效,避免 JSON.stringify 大对象:
const errorFingerprints = new Map();
function getErrorFingerprint(error) {
return error.stack ? btoa(error.stack.slice(0, 200)) : error.message;
}
<p>window.onerror = (msg, url, line, col, error) => {
if (!error) return true;
const fp = getErrorFingerprint(error);
const now = Date.now();
if (errorFingerprints.has(fp) && now - errorFingerprints.get(fp) </p>
- 别用
setTimeout清理 Map —— 页面生命周期长时内存泄漏风险高;改用requestIdleCallback或定时轮询清理过期项 - 如果项目用 Webpack/Vite,
error.stack可能含 sourcemap 路径,上线前确保已剥离或统一替换为占位符,否则指纹不稳定 - 对
Script error.这类跨域错误,无法拿到堆栈,只能用msg + url + line组合生成指纹,准确率下降,需单独标记
合并 document.error 和 unhandledrejection
window.onerror 捕不到 Promise 拒绝和资源加载失败,必须三源合一再做去重:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
-
document.addEventListener('error', e => { ... }, true)捕获所有资源加载失败(<img>、<link>、<object></object>),但e.error为空,靠e.target类型 +e.target.src构建指纹 -
window.addEventListener('unhandledrejection', e => { ... })中取e.reason?.stack || e.reason?.message,注意e.reason可能是字符串或 Error 实例 - 三者共用同一套指纹缓存和限频逻辑,不能各自维护 Map —— 同一网络错误可能先触发
document.error,再触发unhandledrejection
真正难的是“哪些不该去重”
业务关键路径上的错误必须原样上报,哪怕 1 秒内出现 10 次。比如支付页的 AlipaySDK is not defined,重复意味着 SDK 加载链路持续断裂,不是噪音而是故障信号。
不要把去重逻辑写死在埋点 SDK 里。留好钩子,让业务代码能传入 { ignoreDedupe: true } 或匹配 URL 白名单,否则监控系统看到的永远是“已过滤”的残缺数据。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










