有时您可能希望让服务器知道用户正在离开页面。这很有用,例如,清理临时存储在服务器上的未保存图像、将该用户标记为“离线”或在他们完成会话时进行记录。
过去,您会在beforeunload 函数中发送AJAX 请求,但这有两个问题。如果您发送异步请求,则无法保证该请求会正确执行。如果您发送同步请求,它更可靠,但浏览器会挂起,直到请求完成。如果这是一个缓慢的请求,这会给用户带来极大的不便。
后来navigator.sendBeacon()。通过使用sendBeacon() 方法,数据在用户代理有机会时异步传输到Web 服务器,不会延迟卸载或影响下一次导航的性能。这解决了提交分析数据的所有问题:数据发送可靠,异步发送,并且不影响下一页的加载。
除非您只针对桌面用户,否则sendBeacon() should not be used with unload or beforeunload 因为这些在移动设备上并不可靠。相反,您可以收听visibilitychange 事件。每当您的页面可见并且用户切换选项卡、切换应用程序、转到主屏幕、接听电话、离开页面、关闭选项卡、刷新等时,都会触发此事件。
下面是它的用法示例:
document.addEventListener('visibilitychange', function() {
if (document.visibilityState == 'hidden') {
navigator.sendBeacon("/log.php", analyticsData);
}
});
当用户返回页面时,document.visibilityState 将变为'visible',因此您也可以处理该事件。
sendBeacon() 是supported 在:
- 边缘 14
- 火狐31
- 铬 39
- Safari 11.1
- 歌剧 26
- iOS Safari 11.4
目前不支持:
这里是polyfill for sendBeacon(),以防您需要添加对不受支持的浏览器的支持。如果该方法在浏览器中不可用,它将发送一个同步的 AJAX 请求。
更新:
值得一提的是sendBeacon() 只发送POST 请求。如果您需要使用任何其他方法发送请求,另一种方法是使用fetch API 并将keepalive 标志设置为true,这使其行为方式与sendBeacon() 相同。 Browser support for the fetch API 差不多。
fetch(url, {
method: ...,
body: ...,
headers: ...,
credentials: 'include',
mode: 'no-cors',
keepalive: true,
})