Signatur
Beschreibung
Die Methode [Symbol.asyncIterator]() liegt auf %AsyncIteratorPrototype%. Von diesem gemeinsamen Prototyp erben alle eingebauten asynchronen Iteratoren, zum Beispiel die Objekte, die asynchrone Generatorfunktionen (async function*) zurückgeben. Die Umsetzung ist denkbar einfach: Die Methode gibt this zurück, also den Iterator selbst.
Wichtig ist das wegen des asynchronen Iterable-Protokolls. Syntax wie for await...of oder yield* in asynchronen Generatoren ruft zuerst obj[Symbol.asyncIterator]() auf, um an einen Iterator zu kommen. Weil ein asynchroner Iterator sich hier selbst zurückgibt, lässt er sich direkt an diese Stellen übergeben. Man muss ihn also nicht erst in ein eigenes Iterable-Objekt verpacken.
Direkt aufrufen muss man die Methode praktisch nie. Nützlich ist sie vor allem bei eigenen asynchronen Iteratoren: Setzt man %AsyncIteratorPrototype% als Prototyp, erbt das Objekt diese Methode automatisch und kann ohne weiteren Code in for await...of verwendet werden.
Rückgabewert
this, also genau das Iterator-Objekt, auf dem die Methode aufgerufen wurde. Es wird kein neues Objekt erzeugt.Beispiele
Ein asynchroner Generator gibt sich selbst zurück
async function* ladeSeiten() {
yield 'Seite 1';
yield 'Seite 2';
}
const gen = ladeSeiten();
// Die Methode liefert exakt dasselbe Objekt zurück
console.log(gen[Symbol.asyncIterator]() === gen);
console.log(typeof gen[Symbol.asyncIterator]);
Teilweise von Hand lesen, dann mit for await weiterlaufen
// In einem ES-Modul (Top-Level-await) oder in einer async-Funktion ausführen
async function* zahlen() {
yield 1;
yield 2;
yield 3;
}
const it = zahlen();
// Erstes Element manuell holen, z. B. als Kopfzeile
const { value: kopf } = await it.next();
console.log('Kopf:', kopf);
// for await ruft it[Symbol.asyncIterator]() auf, bekommt it selbst
// zurück und setzt deshalb beim aktuellen Stand fort
for await (const n of it) {
console.log('Wert:', n);
}
Eigener asynchroner Iterator erbt die Methode von %AsyncIteratorPrototype%
// Kein globales AsyncIterator-Objekt, daher über einen asynchronen Generator ermitteln
const AsyncIteratorPrototype = Object.getPrototypeOf(
Object.getPrototypeOf((async function* () {}).prototype)
);
const countdown = (start) => {
let aktuell = start;
return Object.setPrototypeOf(
{
async next() {
await new Promise((r) => setTimeout(r, 100));
return aktuell > 0
? { value: aktuell--, done: false }
: { value: undefined, done: true };
},
},
AsyncIteratorPrototype
);
};
(async () => {
// Funktioniert ohne eigene [Symbol.asyncIterator]-Implementierung
for await (const n of countdown(3)) {
console.log(n);
}
})();
// Wichtig · Fallstricke
- Nur einmal durchlaufbar: Weil die Methode
thiszurückgibt, entsteht kein neuer Durchlauf. Ein zweitesfor await...ofüber denselben, bereits verbrauchten Iterator gibt keine Werte mehr aus. Wer mehrfach iterieren will, braucht ein Iterable, das bei jedem Aufruf einen neuen Iterator erzeugt, zum Beispiel ein Objekt mit einemasync *[Symbol.asyncIterator](). - Kein globales
AsyncIterator: Anders alsIterator(ES2025) gibt es derzeit kein globalesAsyncIterator-Objekt. Das kommt erst mit dem Vorschlag Async Iterator Helpers. Den Prototyp erreicht man bis dahin nur überObject.getPrototypeOf, wie in Beispiel 3 gezeigt. - Vorzeitiger Abbruch: Bricht man
for await...ofmitbreak,returnoderthrowab, wirdreturn()des Iterators aufgerufen. Ein Generator gilt danach als beendet, auch wenn er vorher per Hand angelesen wurde. - Rückfall auf synchrone Iterables: Fehlt
[Symbol.asyncIterator], greiftfor await...ofauf[Symbol.iterator]zurück. Normale Arrays aus Promises funktionieren deshalb ebenfalls. - Kompatibilität: Wird von allen modernen Browsern und ab Node.js 10 unterstützt. Top-Level-
awaitwie in Beispiel 2 geht nur in ES-Modulen.