本文以 “前端监控上报数据” 的业务场景,重点解析在 页面实例关闭 时,如何将监控数据上传到服务端的解决方案。 其中,涉及到4种方案,分别为:
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(版本号大于80)已经不支持。 以下是官方的公告片段:
Chrome now disallows synchronous calls to
XMLHTTPRequest()
during page dismissal when the page is being navigated away from or is closed by the user. This applies tobeforeunload
,unload
,pagehide
, andvisibilitychange
.
详细解释可阅读 Disallow Synchronous XMLHTTPRequest\(\) in Page Dismissal[2]
reponse
的返回值创建一个<img>
元素,并设置src
。大部分的浏览器,都会延迟卸载当前页面,优先加载图像。
var data = JSON.stringify({
time: performance.now()
});
const img = new Image();
img.src = `http://api.wangxiaokai.vip/test?${JSON.stringify(data)}`;
复制代码
GET
请求通过HTTP POST
请求,将少量数据使用异步
的方式,发送到服务端。
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();
}
});
复制代码
浏览器端自动判断合适的时机进行发送
不会产生阻塞,影响当前页面的卸载。 不影响下个新页面的加载,不存在性能问题。 另外,数据传输可靠。
navigator.sendBeacon(url);
navigator.sendBeacon(url, data);
复制代码
url
:接收请求的网络地址data
:请求中携带的数据,数据格式可选:ArrayBuffer
,ArrayBufferView
,Blob
,DomString
,FormData
,URLSearchParams
当浏览器将数据成功加入传输队列时,sendBeacon
方法会返回true
,否则返回false
。
注意返回值的时机:成功加入传输队列,而不是服务端的处理成功后的返回。
POST
请求64kb
)visibilitychange
和beforeunload
中使用,其他事件中回调,会丢失数据。image.png
MDN web docs的描述如下 :
The
keepalive
option can be used to allow the request to outlive the page. Fetch with thekeepalive
flag is a replacement for theNavigator.sendBeacon()
[3] API.
标记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,
});
复制代码
image.png
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8