sendBeacon
监听页面在关闭或者刷新时
beforeunload或者 页面正在被卸载前unload触发;
Beacon API用于将少量数据通过post请求发送到服务器;
Beacon是非阻塞请求,不需要响应。
- 场景
Beacon 接口用于将异步和非阻塞请求发送到服务器。Beacon 请求使用 HTTP 协议中的 POST 方法,请求通常不需要响应。这个请求可以保证在页面的 unload 状态从发起到完成之前被发送。而并不需要一个阻塞请求,例如 XMLHttpRequest 。该交互方式非常适合用在监控捕捉数据方面,不需要得到响应。最终要的是:不会延迟页面的卸载或影响下一导航的载入性能。
- 用法
navigator.sendBeacon(url, data);
url:表示data将要被发送到的网络地址;
data:将要发送的ArrayBufferView或Blob,DOMString或者FormData类型的数据。
返回值:当用户代理成功把数据加入传输队列时,
sendBeacon()方法将会返回true,否则返回false。
- 支持的类型
text/plain:发送普通字符串
目前在 Beacon 中最常用的形式:
navigator.sendBeacon(url, JSON.stringify(data));
Bolb类型: 发送Bolb对象
let blob = new Blob([JSON.stringify(data), {
type: 'application/json',
// type: 'application/x-www-form-urlencoded',
}]);
navigator.sendBeacon(url, blob);
application/x-www-form-urlencoded:发送URLSearchParams对象
navigator.sendBeacon(url, new URLSearchParams(data));
multipart/form-data:发送FormData对象
let formData = new FormData();
formData.append('text', '测试');
navigator.sendBeacon(url, formData);
- 实例
记录在页面上停留的时间
let log = function() {
// 测试是否支持 Beacon
if (!navigator.sendBeacon) return true;
const data = {
start: new Date().getTime(),
end: performance.now(),
url: ''
}
navigator.sendBeacon(url, JSON.stringfy(data));
};
window.addEventListener('beforeunload', log);
- 存在的问题
POST提交数据,默认content-type是text-plain。在node + eggjs服务器中获取不到对应的数据this.ctx.request.body(拼接在接口地址后面的数据仍然可以使用this.ctx.request.query获取),数据被存储在this.ctx.req(返回该类型数据IncomingMessage {}),通过 co-body 解析生成需要的字段:
const parse = require('co-body');
const body = await parse.json(this.ctx.req);
unload事件:在Mac的Safari上似乎用安全警告阻止了请求,保险起见可以在beforeunload事件中使用
- 兼容性
