navigator.sendBeacon 关键在于由浏览器后台线程在卸载后尽力发送,应监听 pagehide 事件(排除 bfcache 场景),传 Blob 或 URLSearchParams 数据,遵守同源与大小限制,不依赖响应,并对旧浏览器降级为 Image 打点。
用 navigator.sendBeacon 发送埋点数据,关键不是“关页面那一瞬发出去”,而是让浏览器接管发送时机——它会在页面卸载后、进程退出前,由后台线程尽力完成传输。只要调用成功(返回 true),浏览器就承诺尝试送达,不卡界面、不丢上下文。
pagehide 是最稳妥的触发点:它在页面真正不可见时触发(包括刷新、跳转、关闭、进入 bfcache),且所有现代浏览器(含 iOS Safari)都支持良好。unload 在移动端常被忽略;beforeunload 会强制弹窗、无法获知用户选择,还可能被禁用。
pagehide,检查 event.persisted === false 再发送——若为 true,说明页面进了往返缓存(bfcache),并未真正离开,通常无需上报beforeunload 中调用 sendBeacon,该事件本意是让用户确认是否离开,不适合做异步数据上报sendBeacon 只接受 ArrayBufferView、Blob、DOMString 或 FormData。直接传 JS 对象会失败;用 JSON.stringify() 得到字符串虽可行,但服务端需明确按 text/plain 解析。更推荐:
new Blob([JSON.stringify(data)], {type: 'application/json'}) —— 后端能按标准 JSON 处理new URLSearchParams(data)(data 是键值对对象)—— 自动设为 application/x-www-form-urlencoded,兼容性极佳sendBeacon 遵守同源策略,目标 URL 必须与当前页面同协议、域名、端口。跨域需后端配 CORS,但 sendBeacon 本身不触发预检,所以只支持简单请求(如 POST + text/plain 或 application/x-www-form-urlencoded)。
pg 代替 page),时间戳用毫秒整数而非 ISO 字符串IE 完全不支持,部分老旧 Android 浏览器也缺失。可加一层判断,降级为 Image 像素打点(仅 GET,适合极简日志)或同步 XHR(仅作最后保障,慎用):
if ('sendBeacon' in navigator),成立则走主流程new Image().src = '/log?' + new URLSearchParams(data),适合无敏感内容、低精度统计