Navigator: sendBeacon() 方法

Baseline 已广泛支持

此功能已成熟,可跨多种设备和浏览器版本工作。它自 ⁨2018 年 4 月⁩ 起已在所有浏览器中可用。

navigator.sendBeacon() 方法 异步地将少量数据通过 HTTP POST 请求发送到 Web 服务器。

它旨在用于将分析数据发送到 Web 服务器,并避免了发送分析数据的传统技术(如使用 XMLHttpRequest)的一些问题。

注意: 对于需要发送除 POST 以外的其他方法的请求,或者需要更改请求属性,或者需要访问服务器响应的用例,请使用带有 keepalive 设置为 true 的 fetch() 方法。

语法

js
sendBeacon(url)
sendBeacon(url, data)

参数

url

将接收数据的 URL。可以是相对路径或绝对路径。

data 可选

包含要发送数据的 ArrayBufferTypedArrayDataViewBlob、字符串字面量或对象、FormDataURLSearchParams 对象。

返回值

如果 用户代理成功排队等待传输 data,则 sendBeacon() 方法返回 true。否则,它返回 false

描述

此方法用于分析和诊断代码向服务器发送数据。

发送分析数据时遇到的一个问题是,网站通常希望在用户完成页面交互后发送分析数据:例如,当用户导航到另一个页面时。在这种情况下,浏览器可能即将卸载页面,此时浏览器可能会选择不发送异步 XMLHttpRequest 请求。

过去,网页曾尝试延迟页面卸载足够长的时间来发送数据。为此,它们使用了变通方法,例如:

  • 通过阻塞的同步 XMLHttpRequest 调用提交数据。
  • 创建一个 <img> 元素并设置其 src。大多数用户代理会延迟卸载以加载图像。
  • 创建无操作循环(no-op loop)持续几秒钟。

所有这些方法都会阻塞文档的卸载,这会减慢导航到下一页的速度。下一页无法避免这种情况,因此新页面看起来很慢,尽管这是前一页的过错。

使用 sendBeacon() 方法,数据会在用户代理有机会时异步传输,而不会延迟卸载或下一次导航。这意味着:

  • 数据可靠发送
  • 异步发送
  • 不影响下一页的加载

数据作为 HTTP POST 请求发送。

在会话结束时发送分析数据

网站通常希望在用户完成页面交互后将分析或诊断数据发送到服务器。最可靠的方法是在 visibilitychange 事件上发送数据。

js
document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon("/log", analyticsData);
  }
});

避免 unload 和 beforeunload

过去,许多网站使用 unloadbeforeunload 事件在会话结束时发送分析数据。然而,这极不可靠。在许多情况下,尤其是在移动设备上,浏览器不会触发 unloadbeforeunloadpagehide 事件。例如,在以下情况下,这些事件不会触发:

  1. 用户加载页面并与其交互。
  2. 完成后,他们切换到另一个应用程序,而不是关闭标签页。
  3. 稍后,他们使用手机的应用程序管理器关闭了浏览器应用程序。

此外,unload 事件与现代浏览器实现的后退/前进缓存(bfcache)不兼容。一些浏览器(如 Firefox)通过将包含 unload 处理程序的页面排除在 bfcache 之外来处理这种不兼容性,从而损害了性能。其他浏览器(如 Safari 和 Android 上的 Chrome)通过在用户在同一标签页中导航到另一个页面时触发 unload 事件来处理。

Firefox 也会将包含 beforeunload 处理程序的页面排除在 bfcache 之外。

使用 pagehide 作为回退

为了支持不实现 visibilitychange 的浏览器,请使用 pagehide 事件。与 beforeunloadunload 一样,此事件的触发也不太可靠,尤其是在移动设备上。然而,它与 bfcache 兼容。

示例

以下示例为 visibilitychange 事件指定了一个处理程序。该处理程序调用 sendBeacon() 来发送分析数据。

js
document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon("/log", analyticsData);
  }
});

规范

规范
Beacon
# sendbeacon-method

浏览器兼容性

另见