小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
需求背景
- 在用户离开页面前发送请求,进行数据上报(如统计用户停留时长)
- 编辑界面未保存退出的情况,保存数据以便恢复
不推荐的方案
1. 在 unload / beforeunload 中发送同步请求
※ How axios 和 fetch 都不支持同步请求,因此需要使用原生 AJAX。
sync_test() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
//...
}
xhr.open("GET", "http://xxx/xxx", false);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(null)
}
window.onbeforeunload = function(e) {
sync_test() //发送同步请求
}
※ Result
报错:Uncaught DOMException: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'https://xxxx/': Synchronous XHR in page dismissal.
※ Why
chrome 不支持在页面卸载事件中(unload、beforeunload)发送同步请求。
参考链接: Ajax Synchronous Request Failing in Chrome www.jackpu.com/jie-jue-syn…
※ More
在 unload / brforeunload 中发送同步请求,73、74版的 chrome 是被支持的(也有其他浏览器是支持的)。但即便如此,也不推荐使用同步的 XMLHttpRequest ,因为这样会导致页面卸载被延迟,并影响下一导航的载入,这并对用户不友好。
2. 在 unload / beforeunload 创建图片
通过在unload / brforeunload 中创建一个图片元素并设置它的 src 属性,来延迟卸载以保证数据的发送。
这种方式也不被推荐:不仅编码模式不好,也同样会导致非常差的页面载入性能。
推荐的方案
使用 navigator.sendBeacon 。 使用该方法发送请求,可以保证数据有效送达,且不会阻塞页面的卸载或加载。
※ How
window.onbeforeunload = function(e) {
navigator.sendBeacon(url, data)
}
※ More sendBeacon 的处理结果? sendBeacon 如果成功进入浏览器的发送队列后,会返回true;如果受到队列总数、数据大小的限制后,会返回false。但返回ture,只是表示进入了发送队列,浏览器会尽力保证发送成功,但是否成功了,不会再有任何返回值。
Beacon API用于将少量数据发送到服务器,而无需等待响应。Beacon 专门用于发送数据然后忘记它。我们本并不期待一个响应,而且我们也不会得到响应。—— 使用 Web Beacon API 记录活动
参考链接: