Start · Sprachen · JavaScript · Referenz · AbortController.abort()

AbortController.abort()

Methode

Bricht alle asynchronen Operationen ab, die das zugehörige <code>AbortSignal</code> beobachten, z. B. <code>fetch()</code>-Anfragen oder Event-Listener.

seit JavaScript Baseline: alle modernen Browser (seit 2019); reaso Kategorie: webapi

Signatur

AbortController.prototype.abort(reason)

Beschreibung

Die Methode abort() setzt das an den Controller gebundene AbortSignal (controller.signal) in den abgebrochenen Zustand. Dabei wird signal.aborted auf true gesetzt, signal.reason mit dem Abbruchgrund belegt und am Signal das Ereignis abort ausgelöst. Jede API, die das Signal erhalten hat, reagiert darauf und beendet ihre Arbeit.

Typische Einsatzfälle sind:

  • Abbrechen von fetch()-Anfragen, z. B. bei Suchfeldern mit Autovervollständigung, wenn eine neue Eingabe die alte Anfrage überflüssig macht.
  • Aufräumen mehrerer Event-Listener auf einen Schlag über die Option signal von addEventListener().
  • Abbrechen eigener asynchroner Funktionen, die ein Signal entgegennehmen und auf das abort-Ereignis hören.
  • Abbruch von Streams, Node.js-APIs (fs.readFile, setTimeout aus timers/promises, Kindprozesse) u. v. m.

Wird ein fetch() abgebrochen, wird dessen Promise mit dem Abbruchgrund zurückgewiesen – ohne eigenen Grund ist das eine DOMException mit dem Namen "AbortError". Ein Controller kann nur einmal abbrechen; weitere Aufrufe von abort() haben keine Wirkung. Für neue Operationen muss ein neuer AbortController erzeugt werden.

Parameter

Name Typ Default Beschreibung
$reason any DOMException "AbortError" Optionaler Abbruchgrund. Landet in signal.reason und wird von fetch() u. a. als Ablehnungsgrund der Promise verwendet. Ohne Angabe wird eine DOMException mit Namen "AbortError" erzeugt.

Rückgabewert

Typ
void
Beschreibung
Gibt undefined zurück. Die Wirkung tritt über das Signal ein (aborted, reason, abort-Ereignis).

Beispiele

fetch-Anfrage per Button abbrechen

const controller = new AbortController();

const loadData = async () => {
  try {
    const res = await fetch('https://example.com/grosse-datei.json', {
      signal: controller.signal,
    });
    const data = await res.json();
    console.log('Geladen:', data);
  } catch (err) {
    if (err.name === 'AbortError') {
      console.log('Download abgebrochen');
    } else {
      console.error('Fehler:', err);
    }
  }
};

loadData();
document.querySelector('#cancel').addEventListener('click', () => controller.abort());
Download abgebrochen

Veraltete Suchanfragen abbrechen (Autovervollständigung)

let controller = null;

const search = async (term) => {
  controller?.abort(); // vorherige Anfrage verwerfen
  controller = new AbortController();

  try {
    const res = await fetch(`/api/suche?q=${encodeURIComponent(term)}`, {
      signal: controller.signal,
    });
    return await res.json();
  } catch (err) {
    if (err.name === 'AbortError') return null; // ersetzt durch neuere Anfrage
    throw err;
  }
};

document.querySelector('#suche').addEventListener('input', async (e) => {
  const treffer = await search(e.target.value);
  if (treffer) console.log(treffer);
});

Eigener Abbruchgrund und mehrere Listener entfernen

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

window.addEventListener('resize', () => console.log('resize'), { signal });
window.addEventListener('scroll', () => console.log('scroll'), { signal });

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

// Beide Listener auf einmal entfernen
controller.abort(new Error('Komponente entfernt'));
console.log(signal.aborted);

controller.abort(); // zweiter Aufruf: keine Wirkung
Abgebrochen: Komponente entfernt true

Eigene abbrechbare Funktion (Verzögerung)

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

const controller = new AbortController();
setTimeout(() => controller.abort('Zeit abgelaufen'), 500);

try {
  await delay(2000, { signal: controller.signal });
} catch (reason) {
  console.log('Abbruch:', reason);
}
Abbruch: Zeit abgelaufen

// Wichtig · Fallstricke

  • Nur einmal nutzbar: Nach dem ersten abort() bleibt das Signal dauerhaft abgebrochen. Wer ein bereits abgebrochenes Signal an fetch() übergibt, erhält sofort eine zurückgewiesene Promise. Für jede neue Operation einen neuen Controller anlegen.
  • Fehler unterscheiden: Ein Abbruch landet im catch-Block. Prüfe err.name === 'AbortError', um ihn nicht als echten Fehler zu melden. Mit eigenem reason wird genau dieser Wert geworfen – dann greift die AbortError-Prüfung nicht.
  • Kein Rückgängigmachen auf dem Server: abort() beendet nur die Verbindung auf Clientseite. Hat der Server die Anfrage schon erhalten (z. B. ein POST), kann die Aktion trotzdem ausgeführt worden sein.
  • Nach der Antwort: Ein Abbruch während res.json() bzw. beim Lesen des Bodys bricht auch das Lesen des Streams ab.
  • Zeitlimits: Für einfache Timeouts ist AbortSignal.timeout(ms) kürzer; mehrere Signale lassen sich mit AbortSignal.any() kombinieren (neuere Browser, Node.js 20+).
  • Kompatibilität: abort() ist in allen modernen Browsern verfügbar; der reason-Parameter erst seit ca. Chrome 98, Firefox 97, Safari 15.4 und Node.js 17.2. Der Internet Explorer unterstützt AbortController nicht.