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

瀏覽器相容性

另見