Start · Sprachen · JavaScript · Referenz · new AbortController()

new AbortController()

Methode

Erzeugt ein neues <code>AbortController</code>-Objekt, über dessen <code>signal</code> sich asynchrone Vorgänge wie <code>fetch()</code> oder Event-Listener abbrechen lassen.

seit JavaScript Baseline: alle Browser (seit 2019), Node.js 15+ gl Kategorie: webapi

Signatur

new AbortController()

Beschreibung

Der Konstruktor new AbortController() erzeugt einen Controller, der ein zugehöriges AbortSignal in der Eigenschaft signal bereitstellt. Dieses Signal gibt man an abbrechbare APIs weiter, zum Beispiel an fetch(), addEventListener(), Streams oder viele Node.js-Funktionen (fs.readFile, timers/promises, child_process).

Ein Aufruf von controller.abort(reason) setzt signal.aborted auf true, speichert den Grund in signal.reason und löst auf dem Signal das Ereignis abort aus. Alle Vorgänge, die das Signal beobachten, brechen dann ab. Bei fetch() wird das Promise mit einem DOMException namens AbortError abgelehnt, oder mit dem übergebenen Grund.

Typische Einsätze sind das Abbrechen veralteter Suchanfragen beim Tippen, das Aufräumen in React-useEffect-Hooks, das gebündelte Entfernen mehrerer Event-Listener und das Setzen eigener Zeitlimits. Ein Controller ist für genau einen Abbruch gedacht: Nach abort() bleibt das Signal dauerhaft abgebrochen, für neue Vorgänge braucht man einen neuen Controller.

Rückgabewert

Typ
AbortController
Beschreibung
Eine neue AbortController-Instanz mit der Eigenschaft signal (ein noch nicht abgebrochenes AbortSignal) und der Methode abort(reason?).

Beispiele

Fetch-Anfrage nach Zeitlimit abbrechen

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 3000);

try {
  const response = await fetch('https://api.example.com/daten', {
    signal: controller.signal,
  });
  const daten = await response.json();
  console.log('Geladen:', daten);
} catch (err) {
  if (err.name === 'AbortError') {
    console.log('Anfrage abgebrochen (Zeitlimit)');
  } else {
    throw err;
  }
} finally {
  clearTimeout(timer);
}
Anfrage abgebrochen (Zeitlimit) // falls der Server länger als 3 s braucht

Veraltete Suchanfragen beim Tippen verwerfen

let aktuellerController = null;

const suche = async (begriff) => {
  aktuellerController?.abort(); // vorherige Anfrage abbrechen
  aktuellerController = new AbortController();
  const { signal } = aktuellerController;

  try {
    const res = await fetch(`/api/suche?q=${encodeURIComponent(begriff)}`, { signal });
    const treffer = await res.json();
    console.log(`Treffer für "${begriff}":`, treffer.length);
  } catch (err) {
    if (err.name !== 'AbortError') console.error(err);
  }
};

document.querySelector('#suchfeld')
  .addEventListener('input', (e) => suche(e.target.value));

Mehrere Event-Listener auf einmal entfernen

const controller = new AbortController();
const { signal } = controller;

window.addEventListener('resize', () => console.log('resize'), { signal });
window.addEventListener('scroll', () => console.log('scroll'), { signal });
document.addEventListener('keydown', (e) => console.log('Taste:', e.key), { signal });

// Später, z. B. beim Schließen einer Komponente:
controller.abort();
console.log(signal.aborted);
true

Eigenen Abbruchgrund übergeben und abfragen

const controller = new AbortController();

controller.signal.addEventListener('abort', () => {
  console.log('Abgebrochen:', controller.signal.reason);
}, { once: true });

controller.abort('Benutzer hat abgebrochen');
controller.abort('zweiter Aufruf'); // wirkungslos

console.log(controller.signal.aborted);
Abgebrochen: Benutzer hat abgebrochen true

// Wichtig · Fallstricke

  • Nur einmal verwendbar: Ein abgebrochenes Signal bleibt abgebrochen. Wer es erneut an fetch() übergibt, bekommt sofort eine Ablehnung. Deshalb pro Vorgang einen neuen Controller anlegen.
  • Fehler unterscheiden: Abbrüche kommen im catch an. Mit err.name === 'AbortError' (bzw. 'TimeoutError' bei AbortSignal.timeout()) erkennt man sie. Wird abort(reason) mit einem eigenen Grund aufgerufen, lehnt fetch() mit genau diesem Wert ab und nicht mit einem AbortError.
  • Kein echter Server-Abbruch: Der Abbruch beendet die Verbindung auf Clientseite. Hat der Server die Anfrage schon verarbeitet, etwa bei einem POST, sind ihre Nebenwirkungen trotzdem passiert.
  • Kürzere Alternativen: Für reine Zeitlimits ist AbortSignal.timeout(ms) einfacher. Mehrere Signale lassen sich mit AbortSignal.any([...]) zusammenfassen (neuere Browser, Node.js 20+).
  • Eigene APIs: Wer selbst abbrechbare Funktionen schreibt, sollte zu Beginn signal.throwIfAborted() aufrufen und den abort-Listener am Ende wieder entfernen, sonst entstehen Speicherlecks.
  • Kompatibilität: Läuft in allen aktuellen Browsern (Chrome 66+, Firefox 57+, Safari 12.1+, Edge 16+). signal.reason und abort(reason) gibt es erst seit etwa 2022. In Node.js ist der Konstruktor ab Version 15 global verfügbar. Im Internet Explorer fehlt er, dort braucht man ein Polyfill.