使用场景
为了满足页面统计需要,我们往往需要在页面关闭前(实际时页面卸载前),调用unload方法向服务器上报数据。
基于XMLHttpRequest异步方案
异步方案时在unload,或者beforeunload使用基于XMLHttpRequest Ajax异步请求,但此异步请求存在不可靠。因为如果请求还没有完成,页面已经卸载了,可能导致数据上传不成功。
同步方案
因为异步方案上传数据不可靠,所以添加一些同步的耗时函数,保证请求完成后才返回。如:
- setTimeout检查请求的返回结果
- 创建几秒钟的 no-op 循环来延迟卸载
- 创建一个图片元素并设置它的 src 属性的方法来延迟卸载。
异步转同步示例:把xhr以同步方式打开,集opne的第三个参数
window.addEventListener('unload', logData, false);
function logData() {
var client = new XMLHttpRequest();
client.open("POST", "/log", false); // 第三个参数表明是同步的 xhr
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send(data);
}
Navigator.sendBeacon
以上基于XHR的方式都有各自的问题,异步不可靠,同步耗时。这就是Navigator.sendBeacon要解决的问题。
sendBeacon方法是通过HTTP将少量数据异步传输到Web服务器,它的异步是将请求与当前页面线程脱钩,作为浏览器进程的任务,可以可靠把数据上报到服务器,并且阻塞当前页面的卸载流程。
语法
navigator.sendBeacon(url);
navigator.sendBeacon(url, data);
参数说明:
- url:请求的地址
- data:可选,类型可以是
ArrayBuffer
,ArrayBufferView
,Blob
,DOMString
,FormData
和URLSearchParams
使用示例
document.addEventListener('visibilitychange', function logData() {
if (document.visibilityState === 'hidden') {
navigator.sendBeacon('/log', analyticsData);
}
});