Start · Sprachen · JavaScript · Referenz · AbortSignal.timeout()

AbortSignal.timeout()

Methode

Statische Methode, die ein <code>AbortSignal</code> zurückgibt, das nach <code>time</code> Millisekunden automatisch mit einer <code>TimeoutError</code>-<code>DOMException</code> abbricht.

seit JavaScript Baseline 2023: Chrome 103, Firefox 100, Safari 16, Kategorie: webapi

Signatur

AbortSignal.timeout(time)

Beschreibung

AbortSignal.timeout() erzeugt ein Signal, das nach Ablauf der angegebenen Zeit von selbst abbricht. Damit lassen sich Zeitlimits für fetch(), Streams oder eigene abbrechbare Funktionen in einer Zeile setzen. Einen eigenen AbortController und ein setTimeout() braucht man dafür nicht.

Nach Ablauf der Zeit ist signal.aborted gleich true. signal.reason enthält dann eine DOMException mit dem Namen TimeoutError. Bricht der Nutzer über einen AbortController ab, heißt der Fehler dagegen AbortError. Am Namen des Fehlers erkennt man also, ob ein Zeitlimit überschritten oder bewusst abgebrochen wurde.

Der Timer misst aktive Zeit: Ist das Dokument inaktiv (z. B. im Back-Forward-Cache) oder wurde ein Worker angehalten, läuft der Timer in dieser Zeit nicht weiter. Soll ein Vorgang sowohl nach einer Zeitgrenze als auch manuell abbrechbar sein, kombiniert man mehrere Signale mit AbortSignal.any().

Parameter

Name Typ Default Beschreibung
$time Pflicht number Zeit in Millisekunden bis zum automatischen Abbruch. Erlaubt ist eine nicht-negative ganze Zahl bis Number.MAX_SAFE_INTEGER (Web-IDL-Typ unsigned long long). Negative oder ungültige Werte führen zu einem TypeError.

Rückgabewert

Typ
AbortSignal
Beschreibung
Ein neues AbortSignal, das nach time Millisekunden aktiver Zeit abbricht. Als reason enthält es dann eine DOMException mit dem Namen TimeoutError.

Beispiele

fetch mit Zeitlimit von 5 Sekunden

const ladeDaten = async (url) => {
  try {
    const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return await res.json();
  } catch (err) {
    if (err.name === 'TimeoutError') {
      console.error('Anfrage hat länger als 5 s gedauert.');
    } else if (err.name === 'AbortError') {
      console.error('Anfrage wurde abgebrochen.');
    } else {
      console.error('Netzwerk- oder Serverfehler:', err.message);
    }
    return null;
  }
};

ladeDaten('https://httpbin.org/delay/10');
Anfrage hat länger als 5 s gedauert.

Zeitlimit und Abbrechen-Button mit AbortSignal.any() kombinieren

const controller = new AbortController();
document.querySelector('#abbrechen')
  .addEventListener('click', () => controller.abort());

const signal = AbortSignal.any([
  controller.signal,
  AbortSignal.timeout(10_000)
]);

try {
  const res = await fetch('/api/export', { signal });
  console.log('Export fertig:', res.status);
} catch (err) {
  console.log(err.name === 'TimeoutError' ? 'Zeitüberschreitung' : 'Vom Nutzer abgebrochen');
}
Vom Nutzer abgebrochen (nach Klick auf den Button)

Signal in einer eigenen Funktion auswerten

const warte = (ms, { signal } = {}) => new Promise((resolve, reject) => {
  signal?.throwIfAborted();
  const id = setTimeout(resolve, ms, 'fertig');
  signal?.addEventListener('abort', () => {
    clearTimeout(id);
    reject(signal.reason);
  }, { once: true });
});

const signal = AbortSignal.timeout(100);
warte(1000, { signal })
  .then(console.log)
  .catch((err) => console.log(err.name, signal.aborted));
TimeoutError true

// Wichtig · Fallstricke

  • Fehlernamen unterscheiden: Nach Ablauf der Zeit wirft fetch() einen TimeoutError und keinen AbortError. Wer nur auf AbortError prüft, übersieht Zeitüberschreitungen.
  • Nicht manuell abbrechbar: Das zurückgegebene Signal hat keinen zugehörigen Controller. Für zusätzliches manuelles Abbrechen kombiniert man es per AbortSignal.any() mit einem AbortController-Signal.
  • Neues Signal pro Anfrage: Einmal abgebrochen, bleibt ein Signal abgebrochen. Signale deshalb nicht für Wiederholungsversuche wiederverwenden, sondern bei jedem Versuch AbortSignal.timeout() neu aufrufen.
  • Aktive Zeit: In angehaltenen Workern oder in Dokumenten im Back-Forward-Cache läuft der Timer nicht weiter. Das Signal ist also kein exakter Uhrzeit-Timer.
  • Gesamtdauer bei fetch: Das Zeitlimit gilt für den ganzen Vorgang einschließlich Lesen des Bodys (res.json()). Bricht das Signal während des Lesens ab, wird auch das Lesen des Bodys abgebrochen.
  • Kompatibilität: Chrome/Edge 103+, Firefox 100+, Safari 16+, Node.js 17.3+ (in Node 16.14 experimentell). Für ältere Umgebungen: AbortController mit setTimeout(() => c.abort(), ms).