一、概述
💡 本文将不再讲述如何选择监听页面卸载关闭的事件,如document.visibilitychange(个人推荐)、beforeunload等。请自行查阅使用哪一种以及用途。
- 我们在项目开发中也许会想要实现记录用户停留该页面的时间的埋点
- 然而实现该功能需要在用户离开页面(关闭浏览器、手机切后台等)的时候向服务器发送一个请求 使用传统的请求方式会导致浏览器关闭后请求发送中断
- 因此为了实现以上需求,我们有两种方法可以选择,一个是
navigator.sendBeacon
,另外一个则是鲜为人知的fetch
结合keepalive
属性 - 或许很多人会疑惑,
fetch
也能保证请求不会中断取消吗?当然可以,下面会告诉大家它的使用方式。
二、Navigator.sendBeacon()
首先先根据MDN文档简单介绍一下这个方法:
The navigator.sendBeacon()
method asynchronously sends an HTTP POST request containing a small amount of data to a web server.
navigator.sendBeacon()
方法异步地向web服务器发送包含少量数据的HTTP POST请求。
It's intended to be used for sending analytics data to a web server, and avoids some of the problems with legacy techniques for sending analytics, such as the use of XMLHttpRequest.
它旨在用于将分析数据发送到web服务器,并避免了一些传统技术发送分析的问题,例如使用XMLHttpRequest。
With the sendBeacon() method, the data is transmitted asynchronously when the user agent has an opportunity to do so, without delaying unload or the next navigation. This means:
- The data is sent reliably
- It's sent asynchronously
- It doesn't impact the loading of the next page
The data is sent as an HTTP POST request
使用sendBeacon()
方法,当用户代理有机会异步传输数据时,就会异步传输数据,而不会延迟卸载或下一次导航。这意味着:
- 数据发送可靠
- 异步发送
- 不影响下一页的加载
数据以HTTP POST请求发送
Web sites often want to send analytics or diagnostics to the server when the user has finished with the page. The most reliable way to do this is to send the data on the visibilitychange event:
Web站点通常希望在用户使用完页面后向服务器发送分析或诊断。最可靠的方法
是发送visbilitychange
事件的数据:
document.addEventListener("visibilitychange", function logData() {
if (document.visibilityState === "hidden") {
navigator.sendBeacon("/log", analyticsData);
}
});
developer.mozilla.org/en-US/docs/… 具体看MDN文档
简单来说,使用该方法即便在浏览器关闭卸载之后,它依旧能把通过该方法发送的请求数据发送到服务器上。
不过该方法的缺点也显而易见:
- 只能发送POST请求
- 无法配置请求头header
- 传输的数据量少,并且传输的数据类型只能
[ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)
、Blob
、DOMString
或FormData
三、Fetch也能保证请求可靠?
这就不得不提在查看navigator.sendBeacon()
文档的时候发现的一段话
意思是:对于需要使用POST以外的方法发送请求的用例,或者需要更改任何请求属性的用例,或者需要访问服务器响应的用例,可以使用
fetch()
方法,并将keepalive
设置为true。
接下来我们查看MDN文档可以看到
意思是:keepalive
选项可用于允许请求比页面活得更久。带有keepalive
标志的Fetch
是Navigator.sendBeacon() API
的替代品。
因此我们可以用以下方式替代Navigator.sendBeacon() API
window.fetch('xxx',{
headers:{},
body:{},
keepalive: true
})
用该方式的优点:
- 可以在
header
上携带Authorization
或者其他请求头 - 可以使用别的请求方式发送数据
- 传输的数据不用被限制在
[ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)
、Blob
、DOMString
或FormData
这几种。
缺点:
火狐浏览器的兼容性问题等