-
需求
当卸载(unload)页面时需要将数据上传至服务器 -
传统方法及不足之处
-
a. xmlHttpRequest的同步方法
window.addEventListener('unload', logData, false); function logData() { var client = new XMLHttpRequest(); // 第三个参数表示同步发送 client.open('POST', '/log', false); client.setRequestHeader('Content-Type', 'text/plain;charset=UTF- 8'); client.send(analyticsData); }
这里要注意的是,将请求改为同步以后,会阻塞页面关闭或重新加载的过程,这样就会影响用户体验。
-
b.我们可以通过在 beforeunload 事件处理器中创建一个图片元素并设置它的 src 属性的方法来延迟卸载以保证数据的发送,因为绝大多数浏览器会延迟卸载以保证图片的载入,所以数据可以在卸载事件中发送。
const reportData = (url, data) => { let img = document.createElement('img'); const params = []; Object.keys(data).forEach((key) => { params.push(`${key}=${encodeURIComponent(data[key])}`); }); img.onload = () => img = null; img.src = `${url}?${params.join('&')}`; };
但如果某些浏览器在实现上无法保证图片的载入,就会导致上报数据的丢失。
-
-
sendBeacon的导入
为了解决上述问题,便有了 navigator.sendBeacon 方法,使用该方法发送请求,可以保证数据有效送达,且不会阻塞页面的卸载或加载,并且编码比起上述方法更加简单。
window.onunload = function() {
var obj = {"name":"ws","age":32}
var url = "http://localhost:9001";
// 下面的Blob中的第一个参数数据有大小的限制,需要注意
// var data = new Array(655377);
// new Blob([data.join(",")]就会报错
var blob = new Blob([JSON.stringify(obj)],{type:"application/x-www-form-urlencoded"});
var result = navigator.sendBeacon(url, blob);
};