Beacon API 是浏览器提供的卸载前可靠上报机制,通过 navigator.sendBeacon() 发送 POST 数据,不阻塞页面关闭,支持 Blob、FormData 等格式但不支持自定义 headers,无回调且有 64KB 大小限制。

Beacon API 是浏览器提供的一种专门用于在页面卸载前发送数据的机制,它能确保请求发出且不阻塞页面关闭或跳转。 它不是普通的异步请求(如 fetch 或 XMLHttpRequest),而是“尽力而为”的可靠上报方式——即使用户已关闭标签页、刷新页面或导航离开,浏览器仍会在后台尝试发送数据。
为什么普通异步请求在卸载时不可靠?
当用户触发页面卸载(比如点击链接、关闭标签、刷新、前进后退)时,浏览器会中止所有未完成的 fetch / XHR 请求。即使你用了 fetch(...).catch(...) 或设置了 timeout,这些请求大概率根本没发出去,或者被静默取消。
Beacon 则不同:调用 navigator.sendBeacon() 后,浏览器承诺将数据加入发送队列,并在当前页面彻底卸载前尽可能发出——不等待响应,不阻塞卸载流程,也不受页面状态影响。
如何使用 Beacon API 发送数据?
核心方法是 navigator.sendBeacon(url, data),它只支持 POST 请求,且 data 类型受限:
立即学习“Java免费学习笔记(深入)”;
- 支持
ArrayBufferView(如 Uint8Array)、Blob、FormData、URLSearchParams、字符串(自动设为 text/plain) - 不支持直接传 JSON 对象;需先序列化为字符串或包装成 Blob/FormData
- 不能自定义 headers(如 Authorization、Content-Type 由浏览器自动设置)
简单示例:
// 记录用户停留时长(页面即将离开时上报)
window.addEventListener('beforeunload', () => {
const data = JSON.stringify({
page: window.location.href,
duration: performance.now() - startTime
});
// 自动以 text/plain 发送
navigator.sendBeacon('/log', data);
});
Beacon 的限制与注意事项
它不是万能的,实际使用中要注意这些边界:
- 仅限 POST 方法,无法发 GET 或带自定义头的请求
- 某些低版本浏览器不支持(Chrome 39+、Firefox 31+、Edge 18+、Safari 11.1+;iOS Safari 支持但旧版有 bug)
- 没有回调或 Promise,无法知道是否成功送达(只能服务端记录日志确认)
- 数据大小建议控制在 64KB 以内(部分浏览器有隐式限制)
- 若页面卸载过快(如强制 kill 进程),仍可能丢失(但概率远低于 fetch)
兼容性兜底方案(可选)
如果需要更高可靠性或更复杂数据格式,可组合使用:
- 优先用
sendBeacon - 降级到
fetch(..., { keepalive: true })(部分浏览器支持,行为类似 beacon) - 最后 fallback 为同步 XHR(
xmlhttp.open(..., false))——但会明显卡住页面,仅作极端保底,不推荐常规使用
检测支持性也很简单:
if (navigator.sendBeacon) {
navigator.sendBeacon('/log', payload);
} else {
// 尝试 fetch keepalive 或其他方案
}
基本上就这些。Beacon 不复杂但容易忽略,适合埋点、性能打点、用户行为收尾上报等「发了就好,不必等回执」的场景。











