Signatur
Beschreibung
throw() setzt einen angehaltenen Generator fort. Statt eines Wertes wird dabei eine Ausnahme an der Position des aktuellen yield ausgelöst. Der Generator kann sie mit try...catch abfangen und weiterlaufen, er kann aufräumen (finally) oder die Ausnahme weitergeben.
Fängt der Generator die Ausnahme ab und erreicht danach ein weiteres yield, liefert throw() ein normales Ergebnisobjekt { value, done: false }. Endet er stattdessen mit return, bekommt man { value, done: true }. Fängt er die Ausnahme nicht ab, wird der Generator beendet und die Ausnahme erreicht den Aufrufer von throw().
Typische Einsatzfälle sind Koroutinen-Bibliotheken wie das frühere co oder Redux-Saga: Schlägt ein asynchroner Vorgang fehl, wird der Fehler per gen.throw(err) in den Generator zurückgegeben. Dort lässt er sich wie in einer async-Funktion mit try...catch behandeln. Außerdem nutzt man throw(), um einen Generator von außen gezielt abzubrechen und seine Aufräumlogik auszuführen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $exception Pflicht | any | Der Wert, der im Generator geworfen werden soll. Am besten eine Instanz von Error, damit ein Stacktrace vorhanden ist. |
Rückgabewert
yield oder return erreicht. Wird die Ausnahme nicht abgefangen, gibt es keinen Rückgabewert: Die Ausnahme wird an den Aufrufer weitergereicht.Beispiele
Fehler im Generator abfangen und weiterlaufen
function* zaehler() {
let n = 0;
while (true) {
try {
yield n++;
} catch (err) {
console.log('Abgefangen:', err.message);
n = 0; // Zurücksetzen nach Fehler
}
}
}
const gen = zaehler();
console.log(gen.next());
console.log(gen.next());
console.log(gen.throw(new Error('Reset')));
console.log(gen.next());
Nicht abgefangene Ausnahme beendet den Generator
function* einfach() {
yield 1;
yield 2;
}
const gen = einfach();
gen.next();
try {
gen.throw(new Error('Abbruch'));
} catch (err) {
console.log('Beim Aufrufer:', err.message);
}
console.log(gen.next()); // Generator ist beendet
Mini-Koroutinen-Runner: Promise-Fehler in den Generator zurückgeben
const run = (genFn) => new Promise((resolve, reject) => {
const gen = genFn();
const step = (method, arg) => {
let result;
try {
result = gen[method](arg);
} catch (err) {
return reject(err);
}
if (result.done) return resolve(result.value);
Promise.resolve(result.value).then(
(v) => step('next', v),
(e) => step('throw', e) // Fehler als Ausnahme in den Generator
);
};
step('next');
});
run(function* () {
try {
yield Promise.reject(new Error('Netzwerkfehler'));
} catch (err) {
console.log('Im Generator behandelt:', err.message);
return 'Fallback-Daten';
}
}).then(console.log);
Aufräumen mit finally beim Abbruch
function* ressource() {
console.log('Verbindung geöffnet');
try {
yield 'Daten 1';
yield 'Daten 2';
} finally {
console.log('Verbindung geschlossen');
}
}
const gen = ressource();
gen.next();
try {
gen.throw(new Error('Timeout'));
} catch (e) {
console.log('Fehler:', e.message);
}
// Wichtig · Fallstricke
- Frisch erzeugter Generator: Wurde
next()noch nie aufgerufen, steht der Generator noch vor der ersten Anweisung. Eintry...catchim Körper kann die Ausnahme dann nicht abfangen. Sie wird sofort an den Aufrufer weitergereicht, und der Generator ist danach beendet. - Beendeter Generator: Auch nach
done: truewirftthrow()die übergebene Ausnahme direkt beim Aufrufer. - Läuft der Generator gerade (Aufruf von
throw()aus dem eigenen Körper heraus), entsteht einTypeError(„Generator is already running“). - Wird ein
finally-Block ausgeführt, der selbstyieldenthält, pausiert der Generator dort. Die Ausnahme wird erst später weitergegeben. - Bei
yield*reichtthrow()die Ausnahme an den inneren Iterator weiter. Hat dieser keinethrow-Methode, wird der innere Iterator geschlossen und einTypeErrorausgelöst. - Asynchrone Generatoren haben ein eigenes
AsyncGenerator.prototype.throw(), das ein Promise zurückgibt. - Kompatibilität: in allen modernen Browsern und in Node.js ab 4 verfügbar.