navigator.sendBeacon() 是现代浏览器提供的一个 API,用于在页面卸载(如关闭标签页、导航到其他页面)时,异步且可靠地向服务器发送少量数据(如日志、分析数据等)。它解决了传统 XMLHttpRequest 或 fetch 在页面卸载时可能因浏览器终止任务而失败的问题。
1. 核心特性
- 异步发送
- 数据发送不会阻塞页面卸载流程,适合在 beforeunload、unload 等事件中发送数据。
- 可靠性
- 浏览器会确保数据在后台发送,即使页面已卸载也会尝试完成传输(除非浏览器被强制关闭)。
- 轻量级
- 仅支持发送少量数据(通常限制为几 KB),格式为 Blob、FormData、ArrayBuffer 或字符串。
- 无响应处理
- 该方法返回 boolean,表示浏览器是否接受请求,但不会返回服务器响应(设计初衷是单向通信)。
2. 语法
constsuccess=navigator.sendBeacon(url,data);- url:目标服务器地址(必须同源或支持 CORS)。
- data:要发送的数据(可选),可以是 Blob、FormData、ArrayBuffer 或字符串。
- 返回值:true 表示浏览器已接受请求,false 表示失败(如数据过大或浏览器不支持)。
3. 使用场景
- 页面关闭时发送分析数据
例如记录用户停留时间、最后操作等:window.addEventListener('beforeunload',()=>{constdata=JSON.stringify({event:'page_close',time:Date.now()});navigator.sendBeacon('/analytics',data);}); - 提交表单数据
在卸载前发送用户输入(需配合 FormData):constformData=newFormData();formData.append('feedback','User comment...');navigator.sendBeacon('/submit',formData);
4. 注意事项
- 数据大小限制
不同浏览器限制不同(通常 64KB 左右),超限会返回 false。 - CORS 配置
目标 URL 需支持 CORS(尤其是跨域请求时)。 - 无回调机制
如需确认服务器是否收到数据,需通过其他方式(如后续请求或 WebSocket)。 - 兼容性
现代浏览器均支持,但旧版 IE 不兼容(可用 navigator.sendBeacon 存在性检测)。
5. 与替代方案对比
| 方法 | 阻塞页面卸载 | 可靠性 | 数据大小 | 适用场景 |
|---|---|---|---|---|
| sendBeacon | ❌ 不阻塞 | ✅ 高 | 小 | 页面卸载时发送数据 |
| fetch/XMLHttpRequest | ✅ 阻塞 | ❌ 低 | 大 | 实时交互(如 AJAX) |
| Image 对象 | ❌ 不阻塞 | ❌ 低 | 小 | 简单跟踪(如埋点) |
示例代码
// 发送 JSON 数据constdata=newBlob([JSON.stringify({key:'value'})],{type:'application/json'});constsuccess=navigator.sendBeacon('https://example.com/log',data);if(success){console.log('Beacon queued successfully.');}else{console.error('Failed to send beacon (data too large or unsupported).');}6. 总结
navigator.sendBeacon() 是处理页面卸载时数据上报的最佳实践,尤其适合日志、埋点等场景。它的异步非阻塞特性和高可靠性使其成为传统方法的理想替代方案。使用时需注意数据大小和兼容性,并避免依赖其响应结果。