Fork me on GitHub

信标(Beacon)--数据上传好帮手

本文首发于我的个人Blog阿西BUG,欢迎大家批评指正

前言

日常开发过程中,难免会遇到日志记录相关的需求。有一种需求是需要记录用户在页面停留时间,自然而然的会想到方案:当页面加载时,我们会记录下时间,当用户离开页面时,我们将发送开始时间和当前时间到服务器。
那么我们会使用什么方法来上传信息到服务器呢?
通常是发送一个GET请求(一般是一个带有统计信息的图片请求),使统计服务器获取到数据。
这种方式有以下几个弊端:
1.当页面关闭时,发送的统计请求可能不会成功,导致统计数据丢失。
2.通常为了解决关闭页面的统计数据丢失问题,会发起一个同步的请求,这样会阻塞页面的卸载。
3.GET请求通常有长度限制,可携带的数据量有限,并且一般只能携带文本信息。

那么如何解决上述问题呢?我们引入今天的主角–Beacon API.

什么是Beacon API

MDN 是这样描述的

The Beacon API is used to send an asynchronous and non-blocking request to a web server. The request does not expect a response. Unlike requests made using XMLHttpRequest or the Fetch API, the browser guarantees to initiate beacon requests before the page is unloaded and to run them to completion.

翻译成人话就是

BeaconAPI 用于向 Web 服务器发送异步和非阻塞请求。该请求不期望得到响应。与使用XMLHttpRequest或Fetch API发出的请求不同,浏览器保证在页面卸载之前启动信标请求并运行它们直到完成。

重点是 不期望得到响应,这意味着我们无需等待响应的过程,只需要发送就好了。

Beacon API 使用方法

Beacon 定义了一个方法:navigator.sendBeacon(url, data);
这个接口定义了2个参数,url和要在请求中发送的数据data。其中数据参数是可选的,并且它的类型可以是ArrayBufferViewBlobDOMString,或FormData。如果浏览器成功排队发送请求,该方法返回true;否则,它返回false

需要注意的是:这个方法并不是适用所有的浏览器,因此我们需要在使用前判断当前环境是否支持。

1
2
3
4
5
if (navigator.sendBeacon) {
// Beacon API
} else {
// fallback sync XHR / Fetch API / Axios
}

常见的浏览器兼容情况如图
Beacon API 兼容情况

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let logVisit = function() {
// 测试我们拥有 Beacon 支持
if (!navigator.sendBeacon) return true;

// 数据发送的URL的例子
let url = '/api/log-visit';

// 要发送的数据
let data = new FormData();
data.append('start', startTime);
data.append('end', performance.now());
data.append('url', document.URL);

// 发送
navigator.sendBeacon(url, data);
};

注意,如果没有 Beacon 支持,我们返回 true ,假装一切正常。返回 false 会取消事件并且终止页面卸载。那给用户的感觉就是页面卡住了。

统计数据上报的优雅姿势

这里我们借鉴一片优秀文章的总结:
优雅的数据上报
具体文章戳这里

Enjoy it ? Donate for it ! 欣赏此文?求鼓励,求支持!
>