前端监控数据上报时,为什么用 navigator.sendBeacon 会失败?
我在做前端错误监控,尝试用 navigator.sendBeacon 上报错误日志,但有时候数据根本没发出去,控制台也没报错,特别在页面快关闭的时候。我试过改成 fetch 加 keepalive: true,好像也不稳定。
这是我的上报代码:
function report(data) {
const blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
navigator.sendBeacon('/log', blob);
}
是不是我哪里写错了?还是说 sendBeacon 有啥限制?比如请求头不能自定义之类的?
你提到的 fetch 加 keepalive: true 在某些情况下可能会比 sendBeacon 更可靠,但也有可能因为浏览器兼容性或者网络问题不稳定。
你的代码本身没有明显问题,但可以尝试以下改进:
1. 检查网络状态,确保在发送请求时网络是可达的。
2. 使用 fetch 作为 fallback,当 sendBeacon 失败时,使用 fetch 来发送数据。
3. 确保服务器端正确处理了请求,并返回了成功的响应。
下面是改进后的代码示例:
pre class="pure-highlightjs line-numbers">
function report(data) {
const blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
// 尝试使用 sendBeacon
if (navigator.sendBeacon) {
navigator.sendBeacon('/log', blob);
} else {
// 如果 sendBeacon 不可用,则使用 fetch
fetch('/log', {
method: 'POST',
body: blob,
keepalive: true
}).catch(error => {
console.error('Failed to send data with fetch:', error);
});
}
}
这样可以提高数据上报的成功率。不过也要注意,即使这样处理,也无法保证 100% 成功,因为网络环境是不可控的。
最稳的做法是这样写:
后端记得兼容 text/plain 自己解析 JSON,或者干脆用 fetch + keepalive,这个能自定义 headers。还有 sendBeacon 有数据大小限制大概 64KB,超出也会失败。