Start · Sprachen · JavaScript · Referenz · DeferredRequestInit

DeferredRequestInit

Schnittstelle

Das Optionen-Wörterbuch für <code>fetchLater()</code>: Es konfiguriert eine verzögerte Fetch-Anfrage, zum Beispiel mit einem Zeitlimit über <code>activateAfter</code>.

seit JavaScript Experimentell: Chrome/Edge 135+, noch nicht in Fir Kategorie: webapi

Signatur

interface DeferredRequestInit extends RequestInit

Beschreibung

DeferredRequestInit ist ein Wörterbuch (Dictionary) der Fetch API. Es wird als zweites Argument an fetchLater(resource, options) übergeben. Es enthält alle Optionen aus RequestInit, also method, headers, body, signal, credentials und so weiter. Dazu kommt nur ein neues Feld: activateAfter.

Mit fetchLater() legt man eine Anfrage beim Browser ab, die er später sendet. Das passiert spätestens, wenn das Dokument entladen oder aus dem Back/Forward-Cache entfernt wird. Mit activateAfter kann die Anfrage schon früher gesendet werden, nämlich nach einer Wartezeit in Millisekunden. Damit werden navigator.sendBeacon() und fetch(..., { keepalive: true }) in unload- oder pagehide-Handlern ersetzt. Solche Handler sind unzuverlässig, vor allem auf Mobilgeräten.

Typische Einsätze sind Analysedaten, Sitzungsende-Berichte und das Sammeln von Leistungsmetriken. In all diesen Fällen soll ein Beacon sicher ankommen, auch wenn der Nutzer den Tab schließt. Solange die Anfrage noch nicht gesendet wurde, kann man sie mit einem AbortSignal abbrechen und durch eine neue ersetzen. Das ist ein gängiges Muster, um Daten laufend zu sammeln.

Parameter

Name Typ Default Beschreibung
$activateAfter number (DOMHighResTimeStamp) null (keine Wartezeit, gesendet wird erst beim Entladen) Wartezeit in Millisekunden. Danach sendet der Browser die Anfrage, auch wenn das Dokument noch aktiv ist. Ein negativer Wert löst einen RangeError aus.
$method string "GET" HTTP-Methode, meist "POST" für Beacons.
$headers Headers | Object | Array Anfrage-Header, z. B. { "Content-Type": "application/json" }.
$body string | Blob | FormData | URLSearchParams | ArrayBuffer | TypedArray Anfragekörper. Ein ReadableStream ist nicht erlaubt, denn die Größe muss vorher bekannt sein. Der Körper zählt zum Kontingent für verzögerte Anfragen.
$signal AbortSignal Damit lässt sich die verzögerte Anfrage abbrechen, solange sie noch nicht gesendet wurde.
$credentials "omit" | "same-origin" | "include" "same-origin" Legt fest, ob Cookies und Anmeldedaten mitgesendet werden.
$referrerPolicy string Referrer-Richtlinie der Anfrage.
$priority "high" | "low" | "auto" "auto" Hinweis zur Priorität der Anfrage.

Rückgabewert

Typ
—
Beschreibung
DeferredRequestInit ist ein Optionen-Wörterbuch und hat selbst keinen Rückgabewert. fetchLater() gibt damit ein FetchLaterResult-Objekt zurück. Dessen Eigenschaft activated zeigt an, ob die Anfrage schon gesendet wurde.

Beispiele

Einfacher Sitzungs-Beacon beim Verlassen der Seite

// Wird spätestens gesendet, wenn die Seite entladen wird
const options = {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ event: 'session_end', ts: Date.now() })
};

const result = fetchLater('https://example.com/analytics', options);
console.log(result.activated);
false

Beacon mit Wartezeit über activateAfter

// Nach spätestens 60 Sekunden senden, auch wenn der Tab offen bleibt
const result = fetchLater('/api/heartbeat', {
  method: 'POST',
  body: new URLSearchParams({ page: location.pathname }),
  activateAfter: 60_000
});

setTimeout(() => {
  console.log('Gesendet:', result.activated);
}, 61_000);
Gesendet: true

Laufend gesammelte Daten: alte Anfrage abbrechen und ersetzen

let controller = null;
const metrics = [];

const scheduleReport = () => {
  // Vorherige, noch nicht gesendete Anfrage verwerfen
  controller?.abort();
  controller = new AbortController();

  fetchLater('/api/metrics', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(metrics),
    signal: controller.signal,
    activateAfter: 5 * 60_000 // spätestens nach 5 Minuten
  });
};

document.addEventListener('click', (e) => {
  metrics.push({ tag: e.target.tagName, t: performance.now() });
  scheduleReport();
});

Funktionserkennung mit Rückfall auf sendBeacon

const sendDeferred = (url, data) => {
  const body = JSON.stringify(data);
  if ('fetchLater' in window) {
    try {
      fetchLater(url, { method: 'POST', body, activateAfter: 30_000 });
      return;
    } catch (err) {
      // z. B. QuotaExceededError bei zu großem body
      console.warn('fetchLater fehlgeschlagen:', err.name);
    }
  }
  // Rückfall für Browser ohne fetchLater()
  addEventListener('pagehide', () => navigator.sendBeacon(url, body), { once: true });
};

sendDeferred('/api/log', { level: 'info', msg: 'Seite geladen' });

// Wichtig · Fallstricke

  • Browser-Unterstützung: Die Schnittstelle ist experimentell und derzeit nur in Chromium-Browsern verfügbar (ab Chrome 135). Nutzen Sie immer eine Funktionserkennung mit 'fetchLater' in window und sehen Sie einen Rückfall vor, etwa navigator.sendBeacon().
  • Nur sichere Kontexte: Die Ziel-URL muss HTTPS verwenden (oder localhost). Sonst löst fetchLater() einen TypeError aus.
  • Kein Stream-Körper: Ist body ein ReadableStream, gibt es einen TypeError.
  • Kontingent: Verzögerte Anfragen haben ein begrenztes Kontingent pro Dokument und Origin, standardmäßig rund 64 KiB pro Origin. Beim Überschreiten wird ein QuotaExceededError ausgelöst. Halten Sie Nutzdaten klein, und brechen Sie überholte Anfragen per signal ab, damit sie das Kontingent nicht weiter belegen.
  • keepalive muss man nicht setzen, denn verzögerte Anfragen verhalten sich automatisch so.
  • Einen negativen Wert für activateAfter lehnt der Browser mit einem RangeError ab. Die Wartezeit ist eine Obergrenze. Der Browser kann die Anfrage auch früher senden, zum Beispiel beim Entladen des Dokuments.
  • Eine Antwort des Servers bekommt man nicht zu sehen, denn fetchLater() gibt kein Promise<Response> zurück. Es eignet sich also nur für Anfragen, bei denen man die Antwort nicht braucht.
  • Iframes aus anderen Origins dürfen fetchLater() nur nutzen, wenn die Permissions Policy deferred-fetch es erlaubt.