Wersja próbna origin interfejsu API fetchLater

Brendan Kenny
Brendan Kenny

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ń pagehidevisibilitychange, 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ąpienia Request.
  • Opcjonalny obiekt options, który rozszerza obiekt options z obiektu fetch() o limit czasu o nazwanej activateAfter.

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.

Więcej informacji