2021 年更新
TL;DR
Beacon API 是这个问题的解决方案(在almost every browser)。
即使用户退出页面,信标请求也应该完成。
你应该什么时候触发你的 Beacon 请求?
这将取决于您的用例。如果您正在寻找任何用户退出,visibilitychange(不是unload)是现代浏览器中开发人员的last event reliably observable。
注意:只要visibilitychange 的实现是not consistent across browsers,通过lifecycle.js 库就更容易检测到。
# lifecycle.js (1K) for cross-browser compatibility
# https://github.com/GoogleChromeLabs/page-lifecycle
<script defer src="/path/to/lifecycle.js"></script>
<script defer>
lifecycle.addEventListener('statechange', function(event) {
if (event.originalEvent == 'visibilitychange' && event.newState == 'hidden') {
var URL = "https://example.com/foo";
var data = "bar";
navigator.sendBeacon(URL, data);
}
});
</script>
详情
Beacon requests 应该运行完成,即使用户离开页面 - 切换到另一个应用程序等 - 而不会阻塞用户工作流。
var URL = "https://example.com/foo";
var data = "bar";
navigator.sendBeacon(URL, data);
问题是何时发送您的 Beacon 请求。特别是如果您想等到最后一刻发送会话信息、分析等。
过去在unload 事件期间发送它是一种常见的做法,但页面生命周期管理的更改——由移动用户体验驱动——扼杀了这种方法。今天,大多数移动工作流程(切换到新标签页、切换到主屏幕、切换到另一个应用程序...)do not trigger the unload event at any point。
如果您想在用户退出您的应用/页面时执行操作,现在建议使用visibilitychange 事件并检查从passive 到hidden 状态的转换。
document.addEventListener('visibilitychange', function() {
if (document.visibilityState == 'hidden') {
// send beacon request
}
});
到 hidden 的转换通常是开发人员可以可靠观察到的最后状态变化(在移动设备上尤其如此,因为用户可以关闭选项卡或浏览器应用程序本身,并且不会触发 beforeunload、pagehide 和 unload 事件那些情况)。
这意味着您应该将隐藏状态视为用户会话的可能结束。换言之,保留所有未保存的应用程序状态并发送所有未发送的分析数据。
Page lifecyle API 的详细信息在in this article 中解释。
但是,visibilitychange 事件以及 Page lifecycle API is not consistent across browsers 的实现。
在浏览器实现catches up 之前,使用lifecycle.js 库和page lifecycle best practices 似乎是一个不错的解决方案。
# lifecycle.js (1K) for cross-browser compatibility
# https://github.com/GoogleChromeLabs/page-lifecycle
<script defer src="/path/to/lifecycle.js"></script>
<script defer>
lifecycle.addEventListener('statechange', function(event) {
if (event.originalEvent == 'visibilitychange' && event.newState == 'hidden') {
var URL = "https://example.com/foo";
var data = "bar";
navigator.sendBeacon(URL, data);
}
});
</script>
有关原始页面生命周期事件(没有生命周期.js)的可靠性的更多数字,还有this study。