Start · Sprachen · JavaScript · Referenz · AsyncGeneratorFunction

AsyncGeneratorFunction

Klasse

Das <code>AsyncGeneratorFunction</code>-Objekt stellt den Konstruktor und Methoden für asynchrone Generatorfunktionen bereit, die sowohl <code>async</code> als auch <code>yield</code> kombinieren.

seit JavaScript ES2018 Kategorie: core

Signatur

class AsyncGeneratorFunction

Beschreibung

AsyncGeneratorFunction ist der interne Konstruktor aller asynchronen Generatorfunktionen — also Funktionen, die mit async function* deklariert werden. Eine solche Funktion gibt beim Aufruf ein Async-Generator-Objekt zurück, das sowohl das AsyncIterator- als auch das AsyncIterable-Protokoll implementiert. Dadurch lässt sich die Ausführung per yield pausieren und auf Promises warten (await).

AsyncGeneratorFunction ist nicht direkt als globales Symbol verfügbar. Man erhält eine Referenz darauf über Object.getPrototypeOf(async function* () {}).constructor. In der Praxis erzeugt man asynchrone Generatorfunktionen fast immer mit der async function*-Syntax, nicht über den Konstruktor direkt — letzteres erzeugt ähnlich wie eval zur Laufzeit kompilierte Funktionen und sollte vermieden werden.

Asynchrone Generatorfunktionen eignen sich hervorragend, um asynchrone Datenströme zu erzeugen: z. B. seitenweise API-Anfragen, Zeilen aus einem Stream oder ereignisgesteuerte Sequenzen. Konsumiert werden sie bequem per for await...of-Schleife.

  • yield pausiert die Funktion und liefert einen Wert an den Konsumenten.
  • await suspendiert die Funktion, bis ein Promise aufgelöst ist.
  • yield* delegiert an ein anderes (Async-)Iterable.
  • Jeder .next()-Aufruf auf dem Async-Generator gibt ein Promise<{value, done}> zurück.

Parameter

Name Typ Default Beschreibung
$...args string Wenn AsyncGeneratorFunction direkt als Konstruktor aufgerufen wird (nicht empfohlen), werden zunächst die Parameternamen als Strings übergeben, gefolgt vom Funktionskörper als letztem String-Argument — analog zu new Function(...).

Rückgabewert

Typ
AsyncGenerator
Beschreibung
Ein Async-Generator-Objekt, das AsyncIterator und AsyncIterable implementiert. Dessen .next()-, .return()- und .throw()-Methoden geben jeweils ein Promise<{value: any, done: boolean}> zurück.

Beispiele

Einfacher asynchroner Generator für paginierte API-Daten

// Simulierter API-Aufruf, der eine Seite zurückgibt
const fetchPage = async (page) => {
  // Simulation: 3 Seiten mit je 2 Einträgen
  if (page > 3) return null;
  return { items: [`Item ${page}A`, `Item ${page}B`], page };
};

async function* paginator(startPage = 1) {
  let page = startPage;
  while (true) {
    const result = await fetchPage(page);
    if (!result) return; // Generator beenden
    yield result.items;  // Array der aktuellen Seite liefern
    page++;
  }
}

// Konsumierung per for-await-of
const consume = async () => {
  for await (const items of paginator()) {
    console.log('Seite erhalten:', items);
  }
  console.log('Alle Seiten abgerufen.');
};

consume();
Seite erhalten: [ 'Item 1A', 'Item 1B' ] Seite erhalten: [ 'Item 2A', 'Item 2B' ] Seite erhalten: [ 'Item 3A', 'Item 3B' ] Alle Seiten abgerufen.

Manuelles .next() und früher Abbruch mit .return()

async function* countdown(from) {
  while (from > 0) {
    await new Promise(r => setTimeout(r, 50)); // async-Pause
    yield from--;
  }
}

const gen = countdown(5);

// Ersten drei Werte manuell abrufen
console.log((await gen.next()).value); // 5
console.log((await gen.next()).value); // 4
console.log((await gen.next()).value); // 3

// Generator vorzeitig beenden
const final = await gen.return('abgebrochen');
console.log(final); // { value: 'abgebrochen', done: true }

// Weitere .next()-Aufrufe nach return liefern done: true
console.log(await gen.next()); // { value: undefined, done: true }
5 4 3 { value: 'abgebrochen', done: true } { value: undefined, done: true }

Referenz auf AsyncGeneratorFunction über die Prototyp-Kette

// AsyncGeneratorFunction ist kein globales Symbol — so erhält man die Referenz:
const AsyncGeneratorFunction = Object.getPrototypeOf(async function* () {}).constructor;

console.log(AsyncGeneratorFunction.name); // 'AsyncGeneratorFunction'

// Dynamische Erzeugung (nicht empfohlen – ähnlich wie eval):
const gen = new AsyncGeneratorFunction('x', 'yield x * 2; yield x * 3;');
const iterator = gen(4);

console.log((await iterator.next()).value); // 8
console.log((await iterator.next()).value); // 12
AsyncGeneratorFunction 8 12

// Wichtig · Fallstricke

Sicherheit: Die Verwendung von new AsyncGeneratorFunction(bodyString) ist funktional äquivalent zu eval() — Funktionscode wird zur Laufzeit aus einem String kompiliert. Das öffnet potenzielle Code-Injection-Lücken und verhindert Optimierungen durch die JS-Engine. In Produktionscode sollte ausschließlich die async function*-Syntax verwendet werden.

Fehlerbehandlung: Wird innerhalb eines async Generators ein nicht behandelter Fehler geworfen, wird das von .next() zurückgegebene Promise rejected. Der Generator gilt danach als abgeschlossen (done: true). Per gen.throw(error) kann ein Fehler von außen in den Generator injiziert werden, wo er mit try/catch abgefangen werden kann.

Browser-Kompatibilität: async function* ist seit Chrome 63, Firefox 57, Safari 12 und Node.js 10 verfügbar. In älteren Umgebungen ist ein Transpiler (Babel) mit entsprechenden Plugins nötig.

Speicher: Async-Generatoren halten ihren Scope (Closure) am Leben, bis sie done: true liefern oder per .return() beendet werden. Bei long-running Generatoren (z. B. Endlosschleifen) sollte immer ein Abbruchmechanismus (.return() oder AbortSignal) implementiert werden, um Speicherlecks zu vermeiden.