Signatur
Beschreibung
Die schreibgeschützte Eigenschaft signal gibt das AbortSignal-Objekt zurück, das fest mit einer AbortController-Instanz verbunden ist. Der Controller ist die „Sender-Seite“ und löst den Abbruch über abort() aus. Das Signal ist die „Empfänger-Seite“, die man an asynchrone Vorgänge weitergibt.
Man übergibt das Signal zum Beispiel an fetch(url, { signal }), an addEventListener(type, handler, { signal }), an Streams (pipeTo) oder an viele Node.js-APIs (fs.readFile, setTimeout aus timers/promises, events.once). Sobald controller.abort(reason) aufgerufen wird, wechselt signal.aborted auf true, signal.reason wird gesetzt und am Signal wird ein abort-Event ausgelöst.
Für jeden Controller gibt es immer dasselbe Signal-Objekt: Mehrfaches Lesen von controller.signal liefert dieselbe Instanz. Ein einmal abgebrochenes Signal lässt sich nicht zurücksetzen. Für einen neuen Vorgang braucht man einen neuen AbortController.
So kann man mehrere Vorgänge mit einem einzigen Signal gemeinsam abbrechen. Ein typischer Fall ist das Aufräumen aller Anfragen und Event-Listener, wenn eine Komponente entfernt wird.
Rückgabewert
AbortSignal. Es hat die Eigenschaften aborted und reason, die Methode throwIfAborted() und das Event abort.Beispiele
fetch-Anfrage abbrechen
const controller = new AbortController();
const { signal } = controller;
const ladeDaten = async () => {
try {
const res = await fetch('https://jsonplaceholder.typicode.com/posts', { signal });
const daten = await res.json();
console.log('Geladen:', daten.length);
} catch (err) {
if (err.name === 'AbortError') {
console.log('Anfrage wurde abgebrochen');
} else {
throw err;
}
}
};
ladeDaten();
// z. B. wenn der Nutzer auf „Abbrechen“ klickt:
controller.abort();
Mehrere Event-Listener auf einmal entfernen
const controller = new AbortController();
window.addEventListener('resize', () => console.log('resize'), { signal: controller.signal });
window.addEventListener('scroll', () => console.log('scroll'), { signal: controller.signal });
document.addEventListener('keydown', (e) => console.log(e.key), { signal: controller.signal });
// Aufräumen, z. B. beim Entfernen einer Komponente:
const aufraeumen = () => controller.abort();
aufraeumen();
console.log(controller.signal.aborted);
Eigene abbrechbare Funktion mit Abbruchgrund
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 controller = new AbortController();
setTimeout(() => controller.abort(new Error('Zeitlimit des Nutzers')), 500);
try {
console.log(await warte(2000, controller.signal));
} catch (err) {
console.log('Abgebrochen:', err.message);
}
console.log(controller.signal === controller.signal);
// Wichtig · Fallstricke
- Schreibgeschützt:
controller.signal = …wird im nicht-strikten Modus stillschweigend ignoriert und wirft im strikten Modus einenTypeError. - Nicht wiederverwendbar: Ein abgebrochenes Signal bleibt abgebrochen. Übergibt man es an ein neues
fetch(), wird dieses sofort mit einemAbortErrorabgelehnt. Für jeden neuen Versuch einen neuen Controller anlegen. - Ruft man
abort(reason)mit einem eigenen Grund auf, lehntfetch()mit genau diesem Wert ab, nicht mit einemAbortError. Die Prüfung auferr.name === 'AbortError'greift dann nicht. Ohne Argument istreasoneineDOMExceptionnamensAbortError. - Für reine Zeitlimits ist
AbortSignal.timeout(ms)einfacher, der Fehler heißt dannTimeoutError. Mehrere Signale kombiniert man mitAbortSignal.any([...]), das neuer ist und die Kompatibilität prüfen lässt. - Eigene
abort-Listener am Signal wieder entfernen oder{ once: true }nutzen, besonders bei langlebigen Signalen. Sonst drohen Speicherlecks. - Kompatibilität: in allen modernen Browsern verfügbar.
reasonundthrowIfAborted()gibt es erst seit etwa 2022. In Node.js ist das Signal global verfügbar (stabil ab Version 15).