Często strony internetowe muszą wysyłać dane (lub „beacony”) z powrotem na serwer. Przykładem mogą być dane analityczne o bieżącej sesji użytkownika. Deweloperzy muszą znaleźć złoty środek: ograniczyć częste, być może zbędne żądania, nie ryzykując utraty danych, jeśli karta została zamknięta lub użytkownik przeszedł na inną stronę, zanim beacon został wysłany.
Deweloperzy tradycyjnie używali zdarzeń pagehide
i visibilitychange
, aby uchwycić stronę podczas jej wylogowywania, a potem używali zdarzeń navigator.sendBeacon()
lub fetch()
z parametrem keepalive
, aby pobrać dane z beacona. Oba te zdarzenia mają jednak trudne przypadki, które różnią się w zależności od przeglądarki użytkownika, a czasem zdarzenia wcale nie docierają – zwłaszcza na urządzeniach mobilnych.
fetchLater()
to propozycja zastąpienia tej złożoności pojedynczym wywołaniem interfejsu API. Działa dokładnie tak, jak wskazuje jego nazwa: prosi przeglądarkę o wysłanie żądania w określonym momencie w przyszłości, nawet jeśli strona zostanie zamknięta lub użytkownik opuści witrynę.
fetchLater()
jest dostępna w Chrome do testowania z udziałem prawdziwych użytkowników w ramach testów wersji, które rozpoczną się w wersji 121 (wydana w styczniu 2024 r.) i będą trwać do 3 września 2024 r.
Interfejs API fetchLater()
const fetchLaterResult = fetchLater(request, options);
Funkcja fetchLater()
przyjmuje 2 argumenty, które są zwykle identyczne z argumentami funkcji fetch()
:
request
– ciąg znaków w formie adresu URL lub wystąpieniaRequest
.- Opcjonalny obiekt
options
, który rozszerza obiektoptions
z obiektufetch()
o limit czasu o nazwanejactivateAfter
.
Funkcja fetchLater()
zwraca parametr FetchLaterResult
, który obecnie zawiera tylko jedną właściwość activated
tylko do odczytu, która zostanie ustawiona na true
, gdy minie czas „później” i zostanie wykonane pobieranie. Wszystkie odpowiedzi na prośbę fetchLater()
są ignorowane.
request
Najprostszym sposobem jest podanie samego adresu URL:
fetchLater('/endpoint/');
Jednak podobnie jak w przypadku fetch()
, żądanie fetchLater()
może zawierać wiele opcji, w tym nagłówki niestandardowe, zachowanie danych logowania, treść POST
i opcję AbortController
signal
, która może anulować żądanie.
fetchLater('/endpoint/', {
method: 'GET',
cache: 'no-store',
mode: 'same-origin',
headers: {Authorization: 'SUPER_SECRET'},
});
options
Obiekt options rozszerza opcje obiektu fetch()
o czas oczekiwania activateAfter
, jeśli chcesz uruchomić żądanie po upływie czasu oczekiwania lub po zwolnieniu strony (zależnie, co nastąpi wcześniej).
Dzięki temu możesz zdecydować, czy chcesz otrzymywać dane w ostatniej możliwej chwili, czy w bardziej odpowiednim czasie.
Jeśli np. Twoi użytkownicy zwykle trzymają aplikację otwartą przez cały dzień roboczy, możesz ustawić limit czasu na poziomie godziny, aby zapewnić bardziej szczegółową analizę, a zarazem zagwarantować beacon, jeśli użytkownik zamknie aplikację przed upływem tej godziny. Następnie możesz skonfigurować nowy fetchLater()
na potrzeby kolejnej godziny analityki.
const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});
Przykład użycia
Jednym z problemów podczas pomiarów podstawowych wskaźników internetowych w warunkach rzeczywistych jest to, że wszystkie dane dotyczące wydajności mogą się zmieniać, dopóki użytkownik nie opuści strony. Na przykład w dowolnym momencie może nastąpić większa zmiana układu lub strona może jeszcze dłużej reagować na interakcję.
Nie chcesz jednak ryzykować utraty wszystkich danych o skuteczności z powodu błędnego lub niepełnego beaconowania podczas zwalniania strony. To idealny kandydat na: fetchLater()
.
W tym przykładzie do monitorowania danych używa się biblioteki web-vitals.js, a do raportowania wyników do punktu końcowego Analytics – tagu 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);
Za każdym razem, gdy pojawiają się nowe dane, anulujemy wszystkie zaplanowane fetchLater()
(AbortController
) i tworzymy nowe fetchLater()
z uwzględnieniem aktualizacji.
Wypróbuj model fetchLater()
Jak już wspomnieliśmy, fetchLater()
jest dostępna w ramach testowania origin do wersji Chrome 126. Informacje o testach pochodzenia znajdziesz w artykule „Zaczynaj korzystać z testów pochodzenia”.
W przypadku testów lokalnych możesz włączyć fetchLater
za pomocą flagi funkcji eksperymentalnej platformy internetowej na stronie chrome://flags/#enable-experimental-web-platform-features
. Można go też włączyć, uruchamiając Chrome w wierszu poleceń z flagą --enable-experimental-web-platform-features
lub bardziej ukierunkowaną flagą --enable-features=FetchLaterAPI
.
Jeśli używasz go na stronie publicznej, upewnij się, że funkcja detect jest włączona. Aby to sprawdzić, przed użyciem funkcji sprawdź, czy zdefiniowany jest globalny parametr fetchLater
:
if (globalThis.fetchLater) {
// Set up beaconing using fetchLater().
// ...
}
Prześlij opinię
Opinie deweloperów są niezbędne do prawidłowego działania nowych interfejsów API sieci Web, dlatego przesyłajcie problemy i opinie na GitHub.