Wersja próbna origin interfejsu API fetchLater

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.

fetchLater() zwraca FetchLaterResult, który zawiera obecnie tylko jedną właściwość tylko do odczytu activated. Gdy minie czas podany w parametryetrze „later” i zostanie wykonane pobieranie, wartość tej funkcji zostanie ustawiona na true. Wszystkie odpowiedzi na prośbę fetchLater() są ignorowane.

request

Najprostszym sposobem jest podanie samego adresu URL:

fetchLater('/endpoint/');

Jednak podobnie jak w przypadku fetch(), w żądaniu fetchLater() można ustawić 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 związanych z mierzeniem 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 funkcję 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 okresie próbnym wersji natywnej 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, sprawdź, czy przed użyciem funkcji detect jest zdefiniowana globalna zmienna 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, dlatego przesyłajcie problemy i opinie na GitHub.

Więcej informacji