天天看點

Navigator.sendBeacon()代碼通常嘗試在解除安裝(unload)文檔之前向web伺服器發送資料

​​​

​navigator.sendBeacon()​

​​ 方法可用于通過 ​​HTTP POST​​​ 将少量資料​​異步​​傳輸到 Web 伺服器。

它主要用于将統計資料發送到 Web 伺服器,同時避免了用傳統技術(如:​​XMLHttpRequest​​)發送分析資料的一些問題。

​​文法​​

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

Copy to Clipboard

​​參數​​

​url​

​url​

​​ 參數表明 ​

​data​

​ 将要被發送到的網絡位址。

​data​

​ 可選

​data​

​​ 參數是将要發送的 ​​ArrayBuffer​​​、​​ArrayBufferView​​​、​​Blob​​​、​​DOMString​​​、​​FormData​​​ 或 ​​URLSearchParams​​ 類型的資料。

​​傳回值​​

當使用者代理成功把資料加入傳輸隊列時,​

​sendBeacon()​

​​ 方法将會傳回 ​

​true​

​​,否則傳回 ​

​false​

​。

​​描述​​

這個方法主要用于滿足統計和診斷代碼的需要,這些代碼通常嘗試在解除安裝(unload)文檔之前向web伺服器發送資料。過早的發送資料可能導緻錯過收集資料的機會。然而,對于開發者來說保證在文檔解除安裝期間發送資料一直是一個困難。因為使用者代理通常會忽略在 ​

​unload (en-US)​

​​ 事件處理器中産生的異步 ​​XMLHttpRequest​​。

過去,為了解決這個問題, 統計和診斷代碼通常要在

  • 發起一個同步​

    ​XMLHttpRequest​

    ​ 來發送資料。
  • 建立一個​​<img>​​​ 元素并設定​

    ​src​

    ​,大部分使用者代理會延遲解除安裝(unload)文檔以加載圖像。
  • 建立一個幾秒的 no-op 循環。

上述的所有方法都會迫使使用者代理延遲解除安裝文檔,并使得下一個導航出現的更晚。下一個頁面對于這種較差的載入表現無能為力。

這就是 ​

​sendBeacon()​

​​ 方法存在的意義。使用 ​

​sendBeacon()​

​ 方法會使使用者代理在有機會時異步地向伺服器發送資料,同時不會延遲頁面的解除安裝或影響下一導航的載入性能,這意味着:

  • 資料發送是可靠的。
  • 資料異步傳輸。
  • 不影響下一導航的載入。

資料是通過 ​​HTTP POST​​ 請求發送的。

​​在會話結束時發送統計資料​​

網站通常希望在使用者完成頁面浏覽後向伺服器發送分析或診斷資料,最可靠的方法是在 ​

​visibilitychange (en-US)​

​ 事件發生時發送資料:

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

Copy to Clipboard

​​避免使用 unload 和 beforeunload​​

過去,許多網站使用 ​

​unload (en-US)​

​​ 或 ​

​beforeunload (en-US)​

​​ 事件以在會話結束時發送統計資料。然而這是不可靠的,在許多情況下(尤其是移動裝置)浏覽器不會産生 ​

​unload​

​​、​

​beforeunload​

​​ 或 ​

​pagehide​

​ 事件。下面列出了一種不觸發上述事件的情況:

  1. 使用者加載了網頁并與其互動。
  2. 完成浏覽後,使用者切換到了其它應用程式,而不是關閉頁籤。
  3. 随後,使用者通過手機的應用管理器關閉了浏覽器應用。

此外,​

​unload​

​​ 事件與現代浏覽器實作的往返緩存(​​bfcache​​​)不相容。在部分浏覽器(如:Firefox)通過在 bfcache 中排除包含 ​

​unload​

​​ 事件處理器的頁面來解決不相容問題,但這存在性能損失。其它浏覽器,例如 Safari 和 Android 上的 Chrome 浏覽器則采取使用者在同一标簽頁下導航至其它頁面時不觸發 ​

​unload​

​ 事件的方法來解決不相容問題。

Firefox 也會在 bfcache 中排除包含 ​

​beforeunload​

​ 事件處理器的頁面。

使用 pagehide 作為回退

可使用 ​

​pagehide (en-US)​

​​ 事件來代替部分浏覽器未實作的 ​

​visibilitychange​

​​ 事件。和 ​

​beforeunload​

​​ 與 ​

​unload​

​ 事件類似,這一事件不會被可靠地觸發(特别是在移動裝置上),但它與 bfcache 相容。

​​示例​​

示例代碼使用 ​

​visibilitychange (en-US)​

​​ 事件來調用 ​

​sendBeacon()​

​ 以發送統計資料。

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

Copy to Clipboard

​​規範​​

Specification

Beacon

# sendbeacon-method

Legend

​​參見​​

  • ​visibilitychange (en-US)​

    ​ 事件。
  • ​​Beacon API​​ 概述。
  • ​​Don't lose user and app state, use Page Visibility​​​ 解釋了為什麼你應該使用​

    ​visibilitychange​

    ​​ 而不是​

    ​beforeunload​

    ​​/​

    ​unload​

    ​。
  • ​​網頁生命周期 API​​ 提供了有關在 Web 應用程式中處理網頁生命周期行為的最佳實踐。
  • ​​PageLifecycle.js​​:處理跨浏覽器網頁生命周期行為不一緻的 JavaScript 庫。
  • ​​Back/forward cache​​ 解釋了什麼是往返緩存,以及它對各種網頁生命周期事件的影響。