網頁需要傳送資料 (或「信標」) 回他們的伺服器是很常見的情況,例如使用者目前工作階段的分析資料。對開發人員而言,這需要平衡措施:如果分頁關閉或使用者在傳送信標前就離開,要求減少不變、可能多餘的要求,也不會造成資料遺失的風險。
以往,開發人員會使用pagehide
和visibilitychange
事件在網頁卸載時擷取網頁,然後使用 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 提出問題和意見回饋。