Navigator.sendBeacon:解决页面关闭可靠地上报数据

时间:2022-06-01 17:37:48

使用场景

为了满足页面统计需要,我们往往需要在页面关闭前(实际时页面卸载前),调用unload方法向服务器上报数据。

基于XMLHttpRequest异步方案

异步方案时在unload,或者beforeunload使用基于XMLHttpRequest Ajax异步请求,但此异步请求存在不可靠。因为如果请求还没有完成,页面已经卸载了,可能导致数据上传不成功。

同步方案

因为异步方案上传数据不可靠,所以添加一些同步的耗时函数,保证请求完成后才返回。如:

  1. setTimeout检查请求的返回结果
  2. 创建几秒钟的 no-op 循环来延迟卸载
  3. 创建一个图片元素并设置它的 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);

参数说明:

使用示例

document.addEventListener('visibilitychange', function logData() {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon('/log', analyticsData);
  }
});