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ń 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 czasami 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, ta właściwość 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 momencie.

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 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 pojawi się aktualizacja danych, każda zaplanowana fetchLater() zostaje anulowana (AbortController) i tworzy się nowa fetchLater() z uwzględnieniem aktualizacji.

Wypróbuj model fetchLater()

Jak już wspomnieliśmy, fetchLater() jest dostępna w wersji próbnej origin do 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żesz też włączyć tę funkcję, uruchamiając Chrome z wiersza 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