Start · Sprachen · JavaScript · Referenz · AsyncIterator.prototype[Symbol.asyncIterator]()

AsyncIterator.prototype[Symbol.asyncIterator]()

Methode

Gibt den asynchronen Iterator selbst (<code>this</code>) zurück. Dadurch ist jeder eingebaute asynchrone Iterator auch ein asynchrones Iterable und funktioniert mit <code>for await...of</code>.

seit JavaScript ES2018 Kategorie: method-property

Signatur

AsyncIterator.prototype[Symbol.asyncIterator]()

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

Typ
AsyncIterator
Beschreibung
Den Wert von 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]);
true function

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);
}
Kopf: 1 Wert: 2 Wert: 3

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);
  }
})();
3 2 1

// Wichtig · Fallstricke

  • Nur einmal durchlaufbar: Weil die Methode this zurückgibt, entsteht kein neuer Durchlauf. Ein zweites for 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 einem async *[Symbol.asyncIterator]().
  • Kein globales AsyncIterator: Anders als Iterator (ES2025) gibt es derzeit kein globales AsyncIterator-Objekt. Das kommt erst mit dem Vorschlag Async Iterator Helpers. Den Prototyp erreicht man bis dahin nur über Object.getPrototypeOf, wie in Beispiel 3 gezeigt.
  • Vorzeitiger Abbruch: Bricht man for await...of mit break, return oder throw ab, wird return() 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], greift for await...of auf [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-await wie in Beispiel 2 geht nur in ES-Modulen.