Gebruik de fetchLater() API om op betrouwbare wijze analytische gegevens, Core Web Vitals en telemetriegegevens bij te houden die het hele bezoek van een gebruiker aan een webpagina beslaan (niet alleen tot het laden van de pagina).
De fetchLater() API is de meest betrouwbare manier om gegevens naar een server te sturen als er geen reactie is vereist en de bezorgingstijd niet urgent is. Dit is van toepassing op gegevens zoals gebruikersanalyses, telemetrie, fouten bijhouden en prestatiestatistieken zoals Core Web Vitals.
Oudere technieken, zoals een <img>-pixel maken in een unload-gebeurtenislistener, zijn berucht onbetrouwbaar (vooral op mobiele apparaten) en kunnen de prestaties negatief beïnvloeden (doordat pagina's niet in aanmerking komen voor bfcache).
Hoe wordt dit geïmplementeerd
Het verzoek plannen: Zodra er relevante gegevens beschikbaar zijn, roep je
fetchLater()aan met je gegevenspayload. De gegevens worden dan in de wachtrij geplaatst om later te worden verstuurd.Update de payload zo nodig: Als de gebruiker meer gegevens genereert of de status verandert, breek je het eerder geplande verzoek af en roep je
fetchLater()opnieuw aan met de volledig geüpdatete momentopname.Laat de browser de rest afhandelen: Als de gebruiker weggaat of het tabblad sluit, stuurt de browser de payload van je meest recente
fetchLater()-aanroep op betrouwbare wijze.
Voorbeeldcode
Deze code meet de sessieduur van het bezoek van een gebruiker aan een pagina met fetchLater() om elke 10 seconden een nieuwe beacon in de wachtrij te plaatsen met de geüpdatete sessieduur.
const ANALYTICS_ENDPOINT = '/path/to/analytics/endpoint';
const sessionData = {
duration: 0,
id: crypto.randomUUID(),
};
let fetchLaterController = null;
function queueBeacon() {
// Abort any pending beacons before creating a new one.
if (fetchLaterController) {
fetchLaterController.abort();
}
fetchLaterController = new AbortController();
// Update session duration to the current page time.
sessionData.duration = performance.now();
// Schedule a fetch for the data payload to be sent later.
// IMPORTANT: wrap the call in a try/catch to handle quota errors.
try {
fetchLater(ANALYTICS_ENDPOINT, {
method: 'POST',
headers: {'content-type': 'application/json'},
body: JSON.stringify(sessionData),
signal: fetchLaterController.signal,
});
} catch (error) {
// Handle errors as needed.
}
}
// Update the session data and queue a new beacon every 10 seconds.
setInterval(queueBeacon, 10000);
Praktische tips
- Gebruik
fetchLater()WEL om gegevens naar een server te sturen in situaties waarin een reactie niet nodig is en het niet essentieel is dat de gegevens onmiddellijk worden gestuurd. - Gebruik WEL een
AbortControllerom de in behandeling zijnde ophaalactie te annuleren als de gegevens misschien moeten worden geüpdatet voordat de gebruiker de pagina verlaat. - Zorg dat de payloadgrootte minimaal is om te voorkomen dat het quotum wordt overschreden (op dit moment ongeveer 64 KB per oorsprong).
- WEL: Verpak aanroepen naar
fetchLater()in eentry/catchom quotumfouten af te handelen. - WEL de aanwezigheid van
fetchLater()opglobalThisdetecteren en een fallback-strategie implementeren voor browsers die de API niet ondersteunen. - Gebruik GEEN
ReadableStream-object voor de verzoektekst, omdat dit een fout veroorzaakt.
Browserondersteuning en fallback-strategieën
Er is een reservestrategie vereist als fetchLater() niet voldoet aan uw basislijndoel. Vanwege de verbeterde betrouwbaarheid en prestatievoordelen van deze API moet fetchLater() worden gebruikt als de browser dit ondersteunt.
De aanbevolen fallback-strategie is om de polyfill hieronder te gebruiken. Deze verwerkt intern niet-ondersteunde browsers met fetch() met keepalive of navigator.sendBeacon(). Je eigen code MOET fetchLater() rechtstreeks aanroepen. Roep nooit zelf fetch(), sendBeacon() of andere beacon-API's aan.
fetchLater() polyfill
Gebruik de volgende minimale fetchLater() polyfill, die de API zo nauwkeurig mogelijk implementeert in niet-ondersteunde browsers.
Het enige opmerkelijke verschil in gedrag met deze polyfill is dat deze visibilitychange gebruikt om te detecteren wanneer de gebruiker weggaat, in plaats van te vertrouwen op de systeemeigen verwerking van verwijdering van de browser. Dit is een intern implementatiedetail. Je code hoeft niet te luisteren naar visibilitychange of andere levenscyclusgebeurtenissen van de pagina. Bel gewoon fetchLater() en de polyfill regelt de bezorging.
globalThis.fetchLater ??= function fetchLater(url, init = {}) {
let timeoutHandle;
let activated = false;
function sendNow() {
if (!(init.signal && init.signal.aborted)) {
// Use fetch keepalive if the browser supports it or if custom fetch
// parameters are specified (e.g. custom headers or methods).
// Otherwise fall back to `navigator.sendBeacon()`.
if (
'keepalive' in Request.prototype ||
init.method !== 'POST' ||
init.headers
) {
fetch(url, Object.assign({}, init, {keepalive: true}));
activated = true;
} else {
activated = navigator.sendBeacon(url, init.body);
}
}
destroy();
}
function destroy() {
document.removeEventListener('visibilitychange', sendNow);
clearTimeout(timeoutHandle);
}
if (document.visibilityState === 'hidden') {
// If the beacon was created while the page is already hidden, send data
// ASAP but wait until the next microtask to allow all sync code to run.
queueMicrotask(sendNow);
} else {
document.addEventListener('visibilitychange', sendNow);
if (typeof init.activateAfter === 'number' && init.activateAfter >= 0) {
timeoutHandle = setTimeout(sendNow, init.activateAfter);
}
}
if (init.signal) {
init.signal.addEventListener('abort', destroy);
}
return {
get activated() {
return activated;
},
};
};