此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。

View in English Always switch to English

Navigator.sendBeacon()

基线
广泛可用

自 2018年4月 起,此特性已在主流浏览器中得到支持,可在大多数设备和浏览器版本中正常使用。

navigator.sendBeacon() 方法可用于通过 HTTP POST 将少量数据 异步 传输到 Web 服务器。

它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术(如:XMLHttpRequest)发送分析数据的一些问题。

语法

js
navigator.sendBeacon(url);
navigator.sendBeacon(url, data);

参数

url

url 参数表明 data 将要被发送到的网络地址。

data 可选

data 参数是将要发送的 ArrayBuffer、TypedArray、Blob、String、FormData 或 URLSearchParams 类型的数据。

返回值

当用户代理成功把数据加入传输队列时,sendBeacon() 方法将会返回 true,否则返回 false。

描述

这个方法主要用于满足统计和诊断代码的需要,这些代码通常尝试在卸载(unload)文档之前向 Web 服务器发送数据。过早的发送数据可能导致错过收集数据的机会。然而,对于开发者来说保证在文档卸载期间发送数据一直是一个困难。因为用户代理通常会忽略在 unload 事件处理器中产生的异步 XMLHttpRequest。

过去,为了解决这个问题,统计和诊断代码通常要在

  • 发起一个同步 XMLHttpRequest 来发送数据。
  • 创建一个 <img> 元素并设置 src,大部分用户代理会延迟卸载(unload)文档以加载图像。
  • 创建一个几秒的 no-op 循环。

上述的所有方法都会迫使用户代理延迟卸载文档,并使得下一个导航出现的更晚。下一个页面对于这种较差的载入表现无能为力。

这就是 sendBeacon() 方法存在的意义。使用 sendBeacon() 方法会使用户代理在有机会时异步地向服务器发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能,这意味着:

  • 数据发送是可靠的。
  • 数据异步传输。
  • 不影响下一导航的载入。

数据是通过 HTTP POST 请求发送的。

在会话结束时发送统计数据

网站通常希望在用户完成页面浏览后向服务器发送分析或诊断数据,最可靠的方法是在 visibilitychange 事件发生时发送数据:

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

避免使用 unload 和 beforeunload

过去,许多网站使用 unload 或 beforeunload 事件以在会话结束时发送统计数据。然而这是不可靠的,在许多情况下(尤其是移动设备)浏览器不会产生 unload、beforeunload 或 pagehide 事件。下面列出了一种不触发上述事件的情况:

  1. 用户加载了网页并与其交互。
  2. 完成浏览后,用户切换到了其他应用程序,而不是关闭选项卡。
  3. 随后,用户通过手机的应用管理器关闭了浏览器应用。

此外,unload 事件与现代浏览器实现的往返缓存(bfcache)不兼容。在部分浏览器(如:Firefox)通过在 bfcache 中排除包含 unload 事件处理器的页面来解决不兼容问题,但这存在性能损失。其他浏览器,例如 Safari 和 Android 上的 Chrome 浏览器则采取用户在同一标签页下导航至其他页面时不触发 unload 事件的方法来解决不兼容问题。

Firefox 也会在 bfcache 中排除包含 beforeunload 事件处理器的页面。

使用 pagehide 作为回退

可使用 pagehide 事件来代替部分浏览器未实现的 visibilitychange 事件。和 beforeunload 与 unload 事件类似,这一事件不会被可靠地触发(特别是在移动设备上),但它与 bfcache 兼容。

示例

示例代码使用 visibilitychange 事件来调用 sendBeacon() 以发送统计数据。

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

规范

规范
Beacon
# sendbeacon-method

浏览器兼容性

参见