如何在页面卸载时进行数据上报

1,424 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

需求背景

  1. 在用户离开页面前发送请求,进行数据上报(如统计用户停留时长)
  2. 编辑界面未保存退出的情况,保存数据以便恢复

不推荐的方案

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…

※ Moreunload / 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 记录活动


参考链接: