减少延迟导航
当用户关闭网页或应用时,系统通常会有尚未提交的分析数据或其他数据。为了防止数据丢失,某些网站会使用对 XMLHttpRequest()
的同步调用来使网页或应用保持打开状态,直到其数据传递到服务器为止。不仅有更好的方法来保存数据,而且这种技术还会延迟页面关闭长达数秒,导致糟糕的用户体验。
这种做法需要改变,并且浏览器正在响应。XMLHttpRequest()
规范已计划废弃和移除。Chrome 80 采取了第一步,即禁止在多个事件处理脚本内(具体而言,是 beforeunload
、unload
、pagehide
和 visibilitychange
)在关闭过程中触发这些事件处理脚本时进行同步调用。WebKit 最近也收到了一项实现相同行为变更的提交。
在本文中,我将为需要时间更新网站的用户简要介绍选项,并概述 XMLHttpRequest()
的替代方案。
暂时拒绝
Chrome 并不只是想拔下 XMLHttpRequest()
插头,因此提供了几个临时的停用选项。对于互联网上的网站,可以进行源试用。通过这种方式,您可以向页面标头添加特定于源站的令牌,以启用同步 XMLHttpRequest()
调用。此选项将在 Chrome 89 发布前不久(即 2021 年 3 月的某个时间)结束。Chrome 企业版客户还可以使用 AllowSyncXHRInPageDismissal
政策标志,该标志同时结束。
替代方案
无论您如何发送数据回服务器,最好都不要等到页面卸载后才一次性发送所有数据。除了会造成糟糕的用户体验之外,在新型浏览器中卸载还不可靠,如果出现问题,有可能导致数据丢失。具体而言,卸载事件通常不会在移动浏览器上触发,因为在不触发 unload
事件的情况下,可以通过多种方式关闭移动操作系统上的标签页或浏览器。通过 XMLHttpRequest()
,可以选择使用较小的载荷。现在,这是一项要求按照规范要求,这两种替代方案的上传大小上限为每个上下文 64 KB。
提取 keepalive
Fetch API 提供了一种处理服务器交互的可靠方法,并提供用于不同平台 API 的一致的接口。其中的选项包括 keepalive
,它可确保无论使请求进入的页面是否保持打开状态,请求都会继续执行:
window.addEventListener('unload', {
fetch('/siteAnalytics', {
method: 'POST',
body: getStatistics(),
keepalive: true
});
}
fetch()
方法的优势在于可以更好地控制发送到服务器的内容。我不会在示例中展示的是,fetch()
还会返回一个使用 Response
对象解析的 promise。我想避开网页加载的障碍,因此选择不采取任何操作
SendBeacon()
实际上,SendBeacon()
在后台使用 Fetch API,因此它同样具有 64 KB 的载荷限制,以及它还可以确保请求在页面卸载后继续发出。其主要优势在于简单易用。它可让您通过一行代码提交数据:
window.addEventListener('unload', {
navigator.sendBeacon('/siteAnalytics', getStatistics());
}
总结
随着各浏览器中 fetch()
的可用性不断提高,我们有望在未来某个时候将 XMLHttpRequest()
从 Web 平台中移除。浏览器供应商同意应该将其移除,但这需要一些时间。若要为所有人改善用户体验,第一步就是废弃其中一个最糟糕的用例。
照片由 Matthew Hamilton 拍摄,选自 Unsplash 网站