Start · Sprachen · JavaScript · Referenz · AsyncGenerator.prototype.throw()

AsyncGenerator.prototype.throw()

Methode

Wirft an der aktuell angehaltenen <code>yield</code>-Stelle eines asynchronen Generators einen Fehler und liefert ein Promise auf das nächste Iterator-Ergebnis.

seit JavaScript ES2018 (Baseline: alle modernen Browser, Node.js 1 Kategorie: method-property

Signatur

AsyncGenerator.prototype.throw(exception)

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

Typ
Promise<IteratorResult<any>>
Beschreibung
Ein Promise, das mit { 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')));
{ value: 42, done: false } Fehler abgefangen: Etwas ist schiefgelaufen { value: 42, done: false }

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());
Abgelehnt mit: Abbruch { value: undefined, done: true }

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());
Paket 1 Stream abgebrochen: Timeout { value: 'Fallback-Daten', done: false } Verbindung geschlossen { value: undefined, done: true }

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));
Abgelehnt: zu früh

// Wichtig · Fallstricke

  • Nicht gestarteter Generator: Ruft man throw() vor dem ersten next() auf, wird der Rumpf gar nicht betreten. Ein try...catch im 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() und return() werden intern der Reihe nach abgearbeitet. Ein throw() wirkt also erst, wenn alle vorherigen Anfragen erledigt sind.
  • Zum Abbrechen ohne Fehlerfall ist return() meist die bessere Wahl. Eine for await...of-Schleife ruft beim Verlassen mit break automatisch return() auf, nicht throw().
  • Die Beispiele verwenden await auf oberster Ebene. Das funktioniert nur in ES-Modulen oder in einer umschließenden async-Funktion.
  • Kompatibilität: Chrome 63+, Firefox 55+, Safari 12+, Node.js 10+.