RetrieLater API 來源試用

Brendan Kenny
Brendan Kenny

網頁需要傳送資料 (或「信標」) 回他們的伺服器是很常見的情況,例如使用者目前工作階段的分析資料。對開發人員而言,這需要平衡措施:如果分頁關閉或使用者在傳送信標前就離開,要求減少不變、可能多餘的要求,也不會造成資料遺失的風險。

以往,開發人員會使用pagehidevisibilitychange事件在網頁卸載時擷取網頁,然後使用 navigator.sendBeacon()fetch() 搭配 keepalive 信標資料。然而,這兩種事件的極端情況都因使用者的瀏覽器而異,有時事件甚至永遠不會送達,尤其是在行動裝置上。

fetchLater() 提議將這項複雜性替換為單一 API 呼叫。顧名思義,就是瀏覽器要求瀏覽器確保未來某個時間點提出要求 (即使網頁關閉或使用者離開頁面也一樣)。

自 2024 年 1 月推出 (2024 年 1 月推出) 起,fetchLater() 已開放在 Chrome 中透過來源試用測試,測試環境為實際執行,直到 Chrome 126 版 (2024 年 7 月) 為止。

fetchLater() API

const fetchLaterResult = fetchLater(request, options);

fetchLater() 使用兩個引數,通常與 fetch() 的引數相同:

  • request,字串網址或 Request 執行個體。
  • 選用的 options 物件,可將 fetch() 中的 options 擴充為 activateAfter

fetchLater() 會傳回 FetchLaterResult,目前只包含單一唯讀屬性 activated。如果傳遞「稍後」且擷取完成,這個屬性就會設為 true。系統會捨棄對 fetchLater() 要求的所有回應。

request

最簡單的用途就是只使用一個網址:

fetchLater('/endpoint/');

不過,和 fetch() 一樣,fetchLater() 要求可以設定大量選項,包括自訂標頭、憑證行為、POST 主體,以及 AbortController signal 可能會取消

fetchLater('/endpoint/', {
  method: 'GET',
  cache: 'no-store',
  mode: 'same-origin',
  headers: {Authorization: 'SUPER_SECRET'},
});

options

選項物件會延長 fetch() 的選項,並加上逾時 activateAfter。假設您想在逾時後或頁面卸載時觸發要求 (兩者取其先),

這樣就能在當下的

舉例來說,如果您有一個應用程式使用者通常會在整天保持開啟狀態,您可以將一個小時的逾時時間設為一個小時,以便進行更精細的分析,同時確保使用者在該小時結束前任何時間離開,系統仍能確保系統產生信標。隨後你可以設定新的 fetchLater(),以便在接下來的 1 小時內進行數據分析。

const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});

使用範例

評估欄位中的網站體驗核心指標時,有一個問題是,所有成效指標都可能會變動,直到使用者實際離開網頁為止。舉例來說,如果版面配置的位移不動,隨時都可能發生,或者網頁需要較長時間才能回應互動。

不過,不要擔心頁面卸載時出現錯誤或信標,導致所有成效資料遺失。是fetchLater()的理想選擇。

在這個範例中,web-vitals.js 程式庫是用來監控指標,fetchLater() 則用於將結果回報至數據分析端點:

import {onCLS, onINP, onLCP} from 'web-vitals';

const queue = new Set();
let fetchLaterController;
let fetchLaterResult;

function updateQueue(metricUpdate) {
  // If there was an already complete request for whatever
  // reason, clear out the queue of already-sent updates.
  if (fetchLaterResult?.activated) {
    queue.clear();
  }

  queue.add(metricUpdate);

  // JSON.stringify used here for simplicity and will likely include
  // more data than you need. Replace with a preferred serialization.
  const body = JSON.stringify([...queue]);

  // Abort any existing `fetchLater()` and schedule a new one with
  // the update included.
  fetchLaterController?.abort();
  fetchLaterController = new AbortController();
  fetchLaterResult = fetchLater('/analytics', {
    method: 'POST',
    body,
    signal: fetchLaterController.signal,
    activateAfter: 60 * 60 * 1000, // Timeout to ensure timeliness.
  });
}

onCLS(updateQueue);
onINP(updateQueue);
onLCP(updateQueue);

每次指標更新時,所有已排定的fetchLater()都會透過 AbortController 取消,系統也會透過包含更新項目建立新的 fetchLater()

試用「fetchLater()

如先前所述,fetchLater() 在 Chrome 126 之前開放來源試用。如需來源試用的背景資訊,請參閱「開始使用來源試用

針對本機測試,您可以透過 chrome://flags/#enable-experimental-web-platform-features 的實驗性 Web Platform 功能旗標啟用 fetchLater。您也可以透過指令列執行 Chrome 並加上 --enable-experimental-web-platform-features 或目標更明確的 --enable-features=FetchLaterAPI 旗標,藉此啟用此功能。

如果您在公開網頁上使用此功能,請務必先檢查全域 fetchLater 是否已定義再使用,確保功能進行功能偵測:

if (globalThis.fetchLater) {
  // Set up beaconing using fetchLater().
  // ...
}

意見回饋:

開發人員的意見回饋至關重要,才能正確取得新的 Web API,因此請透過 GitHub 提出問題和意見回饋

更多資訊