Wersja próbna origin interfejsu API fetchLater

Brendan Kenny
Brendan Kenny

Strony internetowe często muszą wysyłać dane (czyli „beacon”) z powrotem na swoje serwery – w tym celu warto na przykład wyświetlić dane analityczne dotyczące bieżącej sesji użytkownika. Z myślą o deweloperach wymaga to równowagi: ograniczanie stałej, potencjalnie nadmiarowej liczby żądań bez ryzyka utraty danych, jeśli karta została zamknięta lub użytkownik przeszedł na inną stronę, zanim możliwe było wysłanie sygnału typu beacon.

Dawniej deweloperzy używali zdarzeń pagehide i visibilitychange, aby wychwycić stronę, gdy jest ona wczytywana, a następnie używali navigator.sendBeacon() lub fetch() z keepalive do wykrywania danych typu beacon. W przypadku obu tych zdarzeń występują jednak trudne przypadki, które różnią się w zależności od przeglądarki użytkownika, a czasem w ogóle nie następuje (zwłaszcza na urządzeniu mobilnym).

fetchLater() to propozycja, która zastąpi tę złożoność pojedynczym wywołaniem interfejsu API. Działa dokładnie tak, jak wskazuje jej nazwa: prosi przeglądarkę o sprawdzenie, czy żądanie zostanie wysłane w przyszłości, nawet jeśli strona zostanie zamknięta lub użytkownik ją opuści.

fetchLater() jest dostępny w Chrome na potrzeby testów z udziałem prawdziwych użytkowników korzystających z wersji próbnej origin od wersji 121 (opublikowanej w styczniu 2024 roku) i działającej do Chrome 126 (lipiec 2024 r.).

Interfejs API fetchLater()

const fetchLaterResult = fetchLater(request, options);

Funkcja fetchLater() przyjmuje 2 argumenty, zasadniczo identyczne z argumentami funkcji fetch():

  • request – adres URL ciągu znaków lub wystąpienie Request.
  • Opcjonalny obiekt options, który rozszerza zakres options z fetch() o czas oczekiwania o nazwie activateAfter.

Funkcja fetchLater() zwraca wartość FetchLaterResult, która obecnie zawiera tylko jedną właściwość tylko do odczytu activated, która jest ustawiona na wartość true po upływie „późniejszego” czasu i zakończeniu pobierania. Każda odpowiedź na żądanie fetchLater() jest odrzucana.

request

Najprostszym sposobem użycia jest adres URL samodzielnie:

fetchLater('/endpoint/');

Jednak, tak jak w przypadku fetch(), w żądaniu fetchLater() można ustawić wiele opcji, w tym niestandardowe nagłówki, działanie danych logowania, treść POST i AbortController signal pozwalające je potencjalnie anulować.

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

options

Obiekt opcji powoduje rozszerzenie opcji fetch() o czas oczekiwania (activateAfter) na wypadek, gdyby użytkownik miał uruchomić żądanie po upływie limitu czasu lub po wyładowaniu strony (w zależności od tego, co nastąpi wcześniej).

Dzięki temu możesz określić kompromis między uzyskaniem danych w ostatniej możliwej chwili czy na czas.

Jeśli np. masz aplikację, w której użytkownicy zwykle pozostają otwarte przez cały dzień pracy, możesz ustawić limit czasu wynoszący godzinę, aby zapewnić bardziej szczegółowe analizy, a jednocześnie gwarantować sygnał typu beacon, jeśli użytkownik opuścił aplikację w dowolnym momencie przed upływem tej godziny. Następnie możesz skonfigurować nowy wskaźnik fetchLater() na następną godzinę analizy.

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

Przykład użycia

Jednym z problemów podczas pomiaru podstawowych wskaźników internetowych w tej dziedzinie jest fakt, że niektóre dane o wydajności mogą się zmieniać, dopóki użytkownik nie opuści strony. Na przykład większe zmiany układu mogą mieć miejsce w dowolnym momencie, a reakcja strony na interakcję może potrwać jeszcze dłużej.

Nie chcesz jednak ryzykować utraty wszystkich danych o skuteczności z powodu błędu lub niepełnego sygnalizowania po wczytaniu strony. To idealna propozycja dla firmy fetchLater().

W tym przykładzie biblioteka web-vitals.js jest używana do monitorowania danych, a fetchLater() do raportowania wyników do punktu końcowego Analytics:

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 wprowadzana jest aktualizacja danych, wcześniej zaplanowany fetchLater() jest anulowany przez element AbortController i tworzony jest nowy element fetchLater() z uwzględnioną aktualizacją.

Wypróbuj model fetchLater()

Zgodnie z informacjami, usługa fetchLater() jest dostępna w wersji próbnej origin do wersji Chrome 126. Więcej informacji na temat testowania origin znajdziesz w sekcji Pierwsze kroki z testami origin.

W przypadku testów lokalnych usługa fetchLater można włączyć za pomocą flagi funkcji eksperymentalnych platformy internetowej pod adresem chrome://flags/#enable-experimental-web-platform-features. Można go również włączyć, uruchamiając Chrome z poziomu wiersza poleceń, używając polecenia --enable-experimental-web-platform-features lub bardziej ukierunkowanej flagi --enable-features=FetchLaterAPI.

Jeśli używasz tagu na stronie publicznej, pamiętaj, aby przed jego użyciem wykryć funkcję, sprawdzając, czy globalny fetchLater jest zdefiniowany:

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

Prześlij opinię

Opinie deweloperów są niezbędne, aby nowe internetowe interfejsy API działały prawidłowo, dlatego zgłaszaj problemy i zgłaszaj je na GitHubie.

Więcej informacji