Start · Sprachen · JavaScript · Referenz · Generator.prototype.next()

Generator.prototype.next()

Methode

Setzt die Ausführung eines Generators bis zum nächsten <code>yield</code> fort und gibt ein Objekt <code>{ value, done }</code> zurück.

seit JavaScript ES2015 Kategorie: method-property

Signatur

Generator.prototype.next(value)

Beschreibung

next() ist die zentrale Methode jedes Generator-Objekts. Bei jedem Aufruf läuft der Generator-Rumpf weiter, bis er auf den nächsten yield-Ausdruck, ein return oder das Ende der Funktion trifft. Zurück kommt ein Iterator-Ergebnisobjekt mit zwei Eigenschaften: value enthält den ausgegebenen Wert, done zeigt an, ob der Generator fertig ist.

Über den optionalen Parameter kann man einen Wert in den Generator hineinreichen: Er wird zum Ergebnis des yield-Ausdrucks, an dem der Generator gerade pausiert. Damit werden Generatoren zu Koroutinen, die in beide Richtungen kommunizieren. So funktionierten auch frühe Bibliotheken für asynchronen Ablauf (etwa co), bevor es async/await gab.

Meistens ruft man next() nicht selbst auf. for...of, der Spread-Operator, Array.from() und die Destrukturierung erledigen das im Hintergrund. Direkte Aufrufe braucht man, wenn man Werte an den Generator übergeben, gezielt einzelne Werte abrufen oder einen Zustandsautomaten Schritt für Schritt steuern will.

Parameter

Name Typ Default Beschreibung
$value any undefined Wert, der an den Generator übergeben wird. Er wird zum Ergebnis des yield-Ausdrucks, an dem der Generator zuletzt angehalten hat. Beim ersten Aufruf von next() wird er ignoriert.

Rückgabewert

Typ
{ value: any, done: boolean }
Beschreibung
Ein Iterator-Ergebnisobjekt. done ist false, solange der Generator bei einem yield pausiert. Beim Abschluss wird es true, und value enthält dann den Wert aus return (sonst undefined).

Beispiele

Grundlegender Ablauf von next()

function* ampel() {
  yield 'rot';
  yield 'gelb';
  yield 'grün';
  return 'aus';
}

const gen = ampel();
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
{ value: 'rot', done: false } { value: 'gelb', done: false } { value: 'grün', done: false } { value: 'aus', done: true } { value: undefined, done: true }

Werte in den Generator hineinreichen (laufende Summe)

function* summierer() {
  let summe = 0;
  while (true) {
    const zahl = yield summe; // erhält den Wert aus next(zahl)
    summe += zahl;
  }
}

const kasse = summierer();
kasse.next();              // Start: läuft bis zum ersten yield, Argument wird ignoriert
console.log(kasse.next(10).value);
console.log(kasse.next(5).value);
console.log(kasse.next(2.5).value);
10 15 17.5

ID-Generator: gezielt einzelne Werte abrufen

function* idGenerator(prefix = 'id') {
  let n = 1;
  while (true) yield `${prefix}-${n++}`;
}

const ids = idGenerator('user');
const neueNutzer = ['Anna', 'Ben'].map(name => ({ id: ids.next().value, name }));
console.log(neueNutzer);
[ { id: 'user-1', name: 'Anna' }, { id: 'user-2', name: 'Ben' } ]

Manuelle Iteration mit Abbruchbedingung

function* seiten() {
  yield ['a', 'b'];
  yield ['c'];
  yield ['d', 'e'];
}

const it = seiten();
const gesammelt = [];
let ergebnis = it.next();
while (!ergebnis.done && gesammelt.length < 3) {
  gesammelt.push(...ergebnis.value);
  ergebnis = it.next();
}
console.log(gesammelt);
[ 'a', 'b', 'c' ]

// Wichtig · Fallstricke

  • Erster Aufruf: Das Argument des ersten next()-Aufrufs geht verloren, weil noch kein yield darauf wartet. Wer den Generator mit einem Anfangswert starten will, übergibt ihn als Parameter an die Generatorfunktion.
  • Der return-Wert bleibt bei for...of unsichtbar: for...of, Spread und Array.from() übergehen den Wert, bei dem done: true ist. Einen Rückgabewert per return sieht man nur bei manuellen next()-Aufrufen.
  • Ausnahmen: Wirft der Generator-Rumpf einen Fehler, gibt next() ihn an den Aufrufer weiter. Danach ist der Generator beendet, und jeder weitere Aufruf liefert { value: undefined, done: true }.
  • Wiedereintritt: Ruft man next() innerhalb des laufenden Generators auf sich selbst auf, gibt es einen TypeError („Generator is already running“).
  • Einmal verbraucht: Ein beendeter Generator lässt sich nicht zurücksetzen. Für einen neuen Durchlauf ruft man die Generatorfunktion erneut auf.
  • Bei asynchronen Generatoren (async function*) liefert next() ein Promise auf das Ergebnisobjekt.
  • Kompatibilität: Alle modernen Browser und Node.js ab Version 4 unterstützen next() (Baseline). Der Internet Explorer kann es nicht.