用户关闭网页或应用时,网页或应用中通常会有未提交的分析数据或其他数据。为防止数据丢失,一些网站会使用对
XMLHttpRequest() 的同步调用,以使网页或应用保持打开状态,直到其数据传递到服务器为止。不仅有更好的数据保存方法,而且这种技术还会将网页关闭延迟长达数秒,从而导致糟糕的用户体验。
这种做法需要改变,浏览器也在做出响应。XMLHttpRequest()
规范已计划弃用和
移除。Chrome 80 takes the first
step by disallowing synchronous calls inside several event handlers,
specifically beforeunload, unload, pagehide, and visibilitychange when
they are fired in the dismissal. WebKit 最近也提交了一个实现相同行为变更的提交。
我将简要介绍需要时间来更新网站的用户的选项,并概述 XMLHttpRequest() 的替代方案。
暂时选择停用
Chrome 希望为开发者提供时间来摆脱对 XMLHttpRequest() 的依赖,因此我们提供了暂时选择停用的选项。
加入来源
试用。这样,您就可以向网页标头添加特定于来源的令牌,以启用同步 XMLHttpRequest()
调用。此选项将在 Chrome 89 发布前不久(大约在 2021 年 3 月)结束。企业版 Chrome
客户还可以使用 AllowSyncXHRInPageDismissal 政策标志,该标志也会在同一时间结束。
替代方案
无论您如何将数据发送回服务器,最好都不要等到网页卸载时才一次性发送所有数据。除了会造成糟糕的用户体验之外,卸载在现代浏览器上也不可靠,如果出现问题,可能会导致数据丢失。具体而言,卸载事件通常不会在移动
浏览器
上触发,因为在移动操作系统上关闭
标签页或浏览器的方式有很多,而不会触发 unload 事件。
使用 XMLHttpRequest() 时,使用小载荷是一种选择。现在,这已成为一项要求。根据规范的要求,这两种替代方案的每个上下文的上传限制均为 64 KB。
Fetch keepalive
Fetch API
提供了一种可靠的方式来处理服务器互动,并提供了一个一致的
接口,以便在不同的
平台 API 中使用。其选项之一是 keepalive,它可确保请求继续,无论发出请求的网页是否保持打开状态:
window.addEventListener('unload', {
fetch('/siteAnalytics', {
method: 'POST',
body: getStatistics(),
keepalive: true
});
}
fetch() 方法的优势在于,它可以更好地控制发送到服务器的内容。我在示例中没有展示的是,fetch()
还会返回一个 promise,该 promise 会解析为 Response 对象。由于我尝试避免妨碍网页卸载,因此我选择不对其执行任何操作。
SendBeacon()
SendBeacon()
实际上在后台使用了 Fetch API,因此它具有相同的 64 KB
载荷限制,并且还可以确保请求在网页卸载后继续。它的主要优势在于简单。它允许您使用一行代码提交数据:
window.addEventListener('unload', {
navigator.sendBeacon('/siteAnalytics', getStatistics());
}
总结
随着 increased availability of
fetch()
在浏览器中的可用性越来越高,XMLHttpRequest() 有望从 Web 平台中移除
。浏览器供应商一致认为应该移除它,但这需要时间。弃用其最糟糕的用例是第一步,这可以改善所有人的用户体验。