Signatur
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.
yieldpausiert die Funktion und liefert einen Wert an den Konsumenten.awaitsuspendiert die Funktion, bis ein Promise aufgelöst ist.yield*delegiert an ein anderes (Async-)Iterable.- Jeder
.next()-Aufruf auf dem Async-Generator gibt einPromise<{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
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();
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 }
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
// 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.