页面卸载时统计数据
目前对于单页面应用来说,统计用户浏览当前页面的时间等数据是个老大难问题,即使是单页面应用,用户关闭当前页面的数据统计也是个困难的问题。目前收集到3种方式
1, XMLHttpRequest 传统同步技术,这个支持类似ajax的发送数据的方式
const data = JSON.stringify({
time: performance.now()
});
var xhr = new XMLHttpRequest();
// 第三个参数false,表示当前请求是同步
xhr.open('post', 'http://api.wangxiaokai.vip/test', false);
xhr.setRequestHeader('content-type', 'application/json');
xhr.onreadystatechange = function() {
// 发送成功后,页面已销毁,所以这里执行不了
}
xhr.send(data);
此方法会导致屏幕出现冻结和无响应的情况,并且新版本的chrome已经不再支持
缺点:
1,用户体验差
2,只有旧版本支持(基本等于用不了,倒是可以考虑兼容的时候用)
3,无法读取返回值
img:src
创建一个img标签,并设置src,大部分浏览器都还延迟卸载当前页面,有些加载图像
var data = JSON.stringify({
time: performance.now()
});
const img = new Image();
img.src = `http://www.xxx.com/test?${JSON.stringify(data)}`;
缺点:
1,不可靠,浏览器可能卸载当前页面,直接忽略图像的请求
2,只能发起get请求
3,数据大小有限制
navigator.sendBeacon+visibilitychange事件
navigator.sendBeacon(url, data);
url:数据要发送的地址
data(可选):是将要发送的 ArrayBuffer、ArrayBufferView、Blob、DOMString、FormData 或 URLSearchParams 类型的数据。
sendBeacon方法会使用户代理在有机会是异步地向服务器发送数据,同事不会延迟嚯影响下一步导航的的载入性能
这就解决了前两种方法的缺点
此方法联合visibilitychange事件即可准确的
visibilityChange事件:判断当前页面的可见性,有以下一些场景
页面有嵌入视频正在播放,当用户切换到其他标签页,你的标签页视频应自动暂停播放,当用户回来时继续播放;
页面自动刷新动作,当用户切换到其他标签页时,因该停止刷新,当用户回来时继续之前的动作;
function reportEvent() {
const url = 'http://api.wangxiaokai.vip/test';
const data = JSON.stringify({
time: performance.now()
});
navigator.sendBeacon(url, data);
}
document.addEventListener('visibilitychange', function() {
if (document.visiblityState === 'hidden') {
reportEvent();
}
});
浏览器端自动判断合适的时机进行发送
并且不会产生阻塞,影响当前页面的卸载,也不会影响下一个页面的加载
返回:
当浏览器将数据成功加入传输队列时,sendBeacon方法会返回true,否则返回false。
注意返回的时机:成功加入传输队列,并不是服务器处理完成
缺点:
1,只能发起POST请求
2,不能自定义请求头参数
3,数据大小有限制,chrome大概64KB
4,只能在window事件visibilitychange和beforeunload中使用,其他事件中回调,会丢失数据。
兼容性
fetch keepalive
标记keepalive的fetch请求允许在页面卸载后执行。
const url = 'http://api.wangxiaokai.vip/test';
const data = JSON.stringify({
time: performance.now()
});
fetch(url, {
method: 'POST',
body: data,
headers: {
'Content-Type': 'application/json'
},
keepalive: true,
});