Start · Sprachen · JavaScript · Referenz · AbortSignal: abort

AbortSignal: abort

Ereignis

Das <code>abort</code>-Ereignis eines <code>AbortSignal</code> wird ausgelöst, sobald das Signal abgebrochen wird, etwa durch <code>AbortController.abort()</code> oder einen Timeout.

seit JavaScript Baseline: alle modernen Browser (seit 2019), Node. Kategorie: webapi

Signatur

signal.addEventListener("abort", handler)

Beschreibung

Das abort-Ereignis tritt genau einmal auf, nämlich wenn ein AbortSignal vom Zustand „nicht abgebrochen“ in „abgebrochen“ wechselt. Dafür gibt es mehrere Wege: Aufruf von AbortController.prototype.abort(), Ablauf eines mit AbortSignal.timeout() erzeugten Signals oder das Abbrechen eines der Quellsignale bei AbortSignal.any(). Wenn das Ereignis ausgelöst wird, sind signal.aborted schon true und signal.reason schon gesetzt.

Man registriert den Handler entweder mit signal.addEventListener("abort", handler) oder über die Eigenschaft signal.onabort = handler. Das Ereignis ist ein einfaches Event ohne Zusatzdaten. Es steigt nicht auf (bubbles), und man kann es nicht abbrechen (nicht cancelable). Den Abbruchgrund liest du über event.target.reason bzw. signal.reason.

Wichtig ist das Ereignis vor allem dann, wenn du eigene abbrechbare APIs baust: Timer, WebSocket-Verbindungen, Worker-Aufgaben oder langlaufende Promises lassen sich so an dasselbe Signal hängen, das auch fetch() steuert. Browser-APIs wie fetch oder addEventListener (Option signal) reagieren intern von selbst auf das Signal, dort brauchst du also keinen eigenen Handler.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignistyp, hier immer "abort".
$handler Pflicht (event: Event) => void | EventListenerObject Callback, der beim Abbruch aufgerufen wird. event.target ist das betroffene AbortSignal.
$options boolean | AddEventListenerOptions false Übliche Optionen von addEventListener. { once: true } ist sinnvoll, damit der Listener nach dem einmaligen Auslösen sicher entfernt wird.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler bekommt ein Event-Objekt mit type === "abort".

Beispiele

Abbruch mit addEventListener beobachten

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

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

controller.abort();
console.log('aborted?', signal.aborted);
Abgebrochen: AbortError aborted? true

onabort-Eigenschaft mit eigenem Grund

const controller = new AbortController();

controller.signal.onabort = () => {
  console.log('Grund:', controller.signal.reason);
};

controller.abort('Benutzer hat abgebrochen');
// Ein zweiter Aufruf löst kein weiteres Ereignis aus
controller.abort('noch einmal');
Grund: Benutzer hat abgebrochen

Eigene abbrechbare Promise (sleep)

const sleep = (ms, { signal } = {}) => new Promise((resolve, reject) => {
  // Bereits abgebrochen? Sofort ablehnen.
  if (signal?.aborted) return reject(signal.reason);

  const onAbort = () => {
    clearTimeout(id);
    reject(signal.reason);
  };
  const id = setTimeout(() => {
    signal?.removeEventListener('abort', onAbort);
    resolve('fertig');
  }, ms);

  signal?.addEventListener('abort', onAbort, { once: true });
});

const run = async () => {
  try {
    await sleep(5000, { signal: AbortSignal.timeout(100) });
  } catch (err) {
    console.log(err.name);
  }
};
run();
TimeoutError

Aufräumen bei abgebrochenem fetch

const controller = new AbortController();
const spinner = document.querySelector('#spinner');

controller.signal.addEventListener('abort', () => {
  spinner.hidden = true;
  console.log('Anfrage abgebrochen, UI zurückgesetzt');
}, { once: true });

document.querySelector('#cancel').onclick = () => controller.abort();

try {
  spinner.hidden = false;
  const res = await fetch('/api/report', { signal: controller.signal });
  console.log(await res.json());
} catch (err) {
  if (err.name !== 'AbortError') throw err;
}
Anfrage abgebrochen, UI zurückgesetzt

// Wichtig · Fallstricke

  • Kein nachträgliches Auslösen: Ist das Signal schon abgebrochen, wenn du den Listener registrierst, wird er nie aufgerufen. Prüfe deshalb vorher signal.aborted oder rufe signal.throwIfAborted() auf.
  • Speicherlecks: Langlebige Signale, etwa ein globaler Controller, sammeln Listener an. Entferne sie mit removeEventListener, wenn die Operation normal endet, und nutze { once: true }.
  • Das Ereignis wird synchron innerhalb von abort() ausgelöst. Code nach controller.abort() läuft also erst, wenn alle Handler durch sind.
  • Löst ein Handler eine Ausnahme aus, wird sie als nicht abgefangener Fehler gemeldet. abort() selbst wirft dabei nicht.
  • Der Standardgrund ist eine DOMException mit dem Namen AbortError, bei AbortSignal.timeout() heißt er TimeoutError.
  • Kompatibilität: abort und onabort gibt es in allen modernen Browsern. reason, timeout() und any() sind jünger (etwa 2022–2023), prüfe sie bei älteren Umgebungen. In Node.js ist AbortSignal ab Version 15 global verfügbar.