前端监控数据上报时,为什么有些错误事件没有被正确上报?

设计师美美 阅读 65

最近在做前端监控功能,用fetch在beforeunload事件上报错误日志,但发现偶尔有数据丢失。明明控制台能看到上报成功的日志,但服务端接收不到,这是什么原因?

尝试过把代码改成同步请求:


window.addEventListener('error', (e) => {
  fetch('/log', {
    method: 'POST',
    body: JSON.stringify({ msg: e.message }),
    keepalive: true // 加了这个属性也没用
  });
});

在页面快速刷新或跳转时尤其容易丢失数据,是不是因为请求没完成就页面关闭了?有没有更可靠的上报方案?

我来解答 赞 13 收藏
二维码
手机扫码查看
2 条解答
UI东宁
UI东宁 Lv1
你这个问题是典型的页面关闭时异步请求被中断导致的数据丢失。用fetch上报监控数据在页面卸载时确实不可靠,即使加了keepalive也不一定能保证请求完成。

直接改成这样:用navigator.sendBeacon,这个是浏览器专门设计用来做可靠上报的API,能保证请求在页面关闭后还能发出去

window.addEventListener('error', (e) => {
const logData = JSON.stringify({ msg: e.message });
navigator.sendBeacon('/log', logData);
});


这玩意儿比fetch靠谱多了,别看控制台显示成功了,那只是请求发出去了不代表服务端真收到了。sendBeacon内部会处理重试和持久化,专门干这种脏活累活的
点赞 4
2026-02-06 23:12
一司翰
一司翰 Lv1
你说的对,问题确实是页面关闭太快导致请求没发出去。fetch虽然有keepalive属性,但在某些浏览器里并不靠谱。同步请求也不推荐,会阻塞主线程,用户体验很差。

更可靠的方案是用 navigator.sendBeacon,专门设计用来在页面卸载时发送数据的。改下你的代码:

window.addEventListener('error', (e) => {
if (navigator.sendBeacon) {
const blob = new Blob([JSON.stringify({ msg: e.message })], { type: 'application/json' });
navigator.sendBeacon('/log', blob);
} else {
// 兼容老浏览器的备选方案
fetch('/log', {
method: 'POST',
body: JSON.stringify({ msg: e.message }),
keepalive: true
});
}
});

window.addEventListener('beforeunload', () => {
// 确保在页面关闭前触发上报
});


sendBeacon 是异步的,不会阻塞主线程,浏览器会保证在页面关闭前把数据发出去。直接复制过去试试,应该不会再丢数据了。

如果还想更保险,可以加个队列机制,先把日志存本地再定时发送,不过这样复杂度会上去。
点赞 8
2026-01-31 06:03