如何在使用者重新整理、跳轉、關閉瀏覽器時向服務端傳送統計的資料?

王铁柱6發表於2024-12-01

在使用者重新整理、跳轉或關閉瀏覽器時向伺服器傳送統計資料,前端開發中常用的方法有以下幾種:

1. 使用navigator.sendBeacon() API:

這是最推薦的方式,尤其是在使用者即將離開頁面時。sendBeacon() 方法非同步傳送少量資料到伺服器,並且不會阻塞頁面解除安裝或影響下一個導航的載入效能。它在瀏覽器後臺傳送資料,即使瀏覽器已經關閉,也能保證資料儘可能地傳送到伺服器。

window.addEventListener('unload', logData);

function logData() {
  if (navigator.sendBeacon) {
    navigator.sendBeacon('/log', JSON.stringify({/* 資料 */}));
  } else {
    // sendBeacon() 不支援時的 fallback,例如使用同步 XMLHttpRequest
    // 但要注意這可能會阻塞頁面解除安裝
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '/log', false); // 使用同步請求
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify({/* 資料 */}));
  }
}

2. 使用XMLHttpRequest (同步):

unloadbeforeunload事件中使用同步的XMLHttpRequest傳送資料。這種方法的缺點是會阻塞頁面解除安裝,影響使用者體驗,並且在某些瀏覽器中可能不被支援或受到限制。 因此,不推薦使用,除非sendBeacon不可用。

window.addEventListener('unload', logData); // 或 beforeunload

function logData() {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/log', false); // 同步請求
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.send(JSON.stringify({/* 資料 */}));
}

3. 使用fetch API (keepalive):

fetch API 的 keepalive 選項允許在頁面解除安裝後繼續傳送請求。這在支援的瀏覽器中可以作為 sendBeacon 的替代方案。

window.addEventListener('unload', logData);

async function logData() {
  try {
    await fetch('/log', {
      method: 'POST',
      body: JSON.stringify({/* 資料 */}),
      keepalive: true
    });
  } catch (error) {
    // 處理錯誤
  }
}

4. 使用 Image 物件 (畫素追蹤):

建立一個 Image 物件,並將其 src 屬性設定為指向伺服器上的一個記錄日誌的指令碼,可以在 URL 中攜帶資料。這種方法的缺點是隻能傳送 GET 請求,並且資料量有限。

window.addEventListener('unload', logData);

function logData() {
  new Image().src = `/log?data=${encodeURIComponent(JSON.stringify({/* 資料 */}))`;
}

事件選擇:

  • unload: 頁面完全解除安裝時觸發。此時文件、資源都已經被移除。由於頁面正在解除安裝,執行時間有限,建議使用 sendBeacon
  • beforeunload: 在頁面解除安裝前觸發,可以取消解除安裝。如果在該事件處理函式中返回一個非空字串,瀏覽器會顯示一個確認對話方塊,詢問使用者是否要離開頁面。 要注意的是,在移動端瀏覽器中,beforeunload 事件可能不被支援或行為不一致。

資料格式:

建議使用 JSON 格式來傳送資料,方便伺服器端處理。

伺服器端:

伺服器端需要設定相應的路由來接收和處理這些資料。

總結:

navigator.sendBeacon() 是目前最好的選擇,因為它不會阻塞頁面解除安裝,並且能夠保證資料儘可能地傳送到伺服器。如果瀏覽器不支援 sendBeacon,可以考慮使用 fetch with keepalive,最後才考慮使用同步的 XMLHttpRequest 或 Image 物件。 選擇哪種方法取決於你的具體需求和瀏覽器相容性要求。 記住測試不同瀏覽器和場景下的相容性。

相關文章