Signatur
Beschreibung
throw() setzt einen angehaltenen asynchronen Generator fort, und zwar so, als stünde an der aktuellen yield-Position die Anweisung throw exception;. Damit kannst du von außen einen Fehler in den Generator hineinreichen, statt nur Werte mit next() zu übergeben.
Fängt der Generator den Fehler mit try...catch ab und erreicht danach ein weiteres yield, wird das zurückgegebene Promise mit { value, done: false } erfüllt. Fängt er ihn nicht ab, wird der Generator beendet und das Promise mit genau diesem Fehler abgelehnt. Ein finally-Block läuft in beiden Fällen, sodass Ressourcen sauber freigegeben werden können.
Das ist praktisch, um lang laufenden Datenströmen (Polling, Paging, Streams) Fehlersituationen wie Zeitüberschreitungen oder Abbrüche mitzuteilen. Der Generator kann dann selbst entscheiden: erneut versuchen, auf Ersatzdaten ausweichen oder aufräumen und beenden.
Wurde der Generator noch gar nicht gestartet (bisher kein next()), läuft sein Rumpf überhaupt nicht an: Er wird sofort beendet und das Promise abgelehnt. Das Gleiche gilt für einen Generator, der schon fertig ist.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $exception Pflicht | any | Der Wert, der an der angehaltenen Stelle geworfen wird. Üblich ist eine Error-Instanz, weil sie zur Fehlersuche einen Stacktrace mitbringt. Jeder andere Wert ist aber ebenfalls erlaubt. |
Rückgabewert
{ value, done } erfüllt wird, wenn der Generator den Fehler abfängt und danach erneut yield erreicht (done: false) oder regulär mit return endet (done: true). Bleibt der Fehler unbehandelt, wird das Promise mit exception abgelehnt.Beispiele
Fehler im Generator abfangen und weitermachen
async function* werteQuelle() {
while (true) {
try {
yield 42;
} catch (err) {
console.log('Fehler abgefangen:', err.message);
}
}
}
const gen = werteQuelle();
console.log(await gen.next());
console.log(await gen.throw(new Error('Etwas ist schiefgelaufen')));
Unbehandelter Fehler: Promise wird abgelehnt, Generator ist beendet
async function* zaehler() {
yield 1;
yield 2;
}
const it = zaehler();
await it.next();
try {
await it.throw(new Error('Abbruch'));
} catch (err) {
console.log('Abgelehnt mit:', err.message);
}
// Der Generator ist jetzt abgeschlossen
console.log(await it.next());
Praxis: Timeout an einen Datenstrom melden, Ersatzdaten liefern, aufräumen
const warte = (ms) => new Promise((r) => setTimeout(r, ms));
async function* lesePakete() {
try {
let i = 0;
while (true) {
await warte(100);
yield `Paket ${++i}`;
}
} catch (err) {
console.log('Stream abgebrochen:', err.message);
yield 'Fallback-Daten';
} finally {
console.log('Verbindung geschlossen');
}
}
const stream = lesePakete();
console.log((await stream.next()).value);
console.log(await stream.throw(new Error('Timeout')));
console.log(await stream.next());
throw() vor dem ersten next(): Rumpf läuft nicht an
async function* gen() {
try {
console.log('Start');
yield 1;
} catch {
console.log('Wird nie ausgegeben');
}
}
const it = gen();
it.throw(new Error('zu früh'))
.catch((err) => console.log('Abgelehnt:', err.message));
// Wichtig · Fallstricke
- Nicht gestarteter Generator: Ruft man
throw()vor dem erstennext()auf, wird der Rumpf gar nicht betreten. Eintry...catchim Generator kann den Fehler dann nicht abfangen. Das Promise wird direkt abgelehnt. - Immer mit
await/.catch()behandeln: Ein unbehandelter Fehler führt zu einem abgelehnten Promise. Wird es ignoriert, gibt es eine unhandled rejection, in Node.js standardmäßig sogar einen Prozessabbruch. - Warteschlange: Aufrufe von
next(),throw()undreturn()werden intern der Reihe nach abgearbeitet. Einthrow()wirkt also erst, wenn alle vorherigen Anfragen erledigt sind. - Zum Abbrechen ohne Fehlerfall ist
return()meist die bessere Wahl. Einefor await...of-Schleife ruft beim Verlassen mitbreakautomatischreturn()auf, nichtthrow(). - Die Beispiele verwenden
awaitauf oberster Ebene. Das funktioniert nur in ES-Modulen oder in einer umschließendenasync-Funktion. - Kompatibilität: Chrome 63+, Firefox 55+, Safari 12+, Node.js 10+.