Signatur
Beschreibung
Iterator.prototype[Symbol.dispose]() implementiert das Disposable-Protokoll für alle Iteratoren, die von Iterator.prototype erben. Das sind unter anderem Generator-Objekte, Array-, Map- und Set-Iteratoren sowie die Ergebnisse von Iterator-Helfern wie map() oder filter(). Die Methode prüft, ob der Iterator eine return()-Methode hat. Wenn ja, ruft sie diese ohne Argumente auf. Der Rückgabewert von return() wird verworfen.
Nützlich ist das, wenn du einen Iterator von Hand mit next() durchläufst und ihn vorzeitig verlassen willst. Eine for...of-Schleife ruft return() bei break, return oder einer Ausnahme schon von selbst auf. Bei manueller Steuerung musst du dich dagegen selbst darum kümmern. Mit using it = gen(); erledigt die Laufzeitumgebung das beim Verlassen des Blocks automatisch, auch wenn eine Ausnahme auftritt.
Bei Generatoren sorgt der Aufruf von return() dafür, dass offene finally-Blöcke laufen. So werden etwa Dateihandles, Sperren oder Verbindungen freigegeben. Iteratoren ohne eigene Aufräumlogik (z. B. Array-Iteratoren ohne return()) macht die Methode zu einem harmlosen Aufruf, der nichts bewirkt.
Rückgabewert
undefined zurück. Das Ergebnis eines eventuellen return()-Aufrufs wird verworfen.Beispiele
Generator mit using automatisch schließen
function* leseZeilen() {
console.log('Ressource geöffnet');
try {
yield 'Zeile 1';
yield 'Zeile 2';
yield 'Zeile 3';
} finally {
console.log('Ressource geschlossen');
}
}
{
using zeilen = leseZeilen();
console.log(zeilen.next().value);
// Nur den Kopf lesen, dann Block verlassen
}
console.log('Nach dem Block');
Manueller Aufruf von [Symbol.dispose]()
function* zaehler() {
try {
let i = 0;
while (true) yield i++;
} finally {
console.log('Zähler beendet');
}
}
const it = zaehler();
it.next();
it.next();
const ergebnis = it[Symbol.dispose]();
console.log(ergebnis);
console.log(it.next());
Eigener Iterator mit Aufräumlogik (Unterklasse von Iterator)
class Abfrage extends Iterator {
#zeilen = ['Anna', 'Ben', 'Clara'];
#index = 0;
next() {
return this.#index < this.#zeilen.length
? { value: this.#zeilen[this.#index++], done: false }
: { value: undefined, done: true };
}
return() {
console.log('Datenbank-Cursor freigegeben');
return { value: undefined, done: true };
}
}
const ersterTreffer = () => {
using cursor = new Abfrage();
return cursor.next().value;
};
console.log(ersterTreffer());
Iterator-Helfer geben das Schließen weiter
function* quelle() {
try {
yield* [1, 2, 3, 4, 5];
} finally {
console.log('Quelle geschlossen');
}
}
{
using gerade = quelle().filter((n) => n % 2 === 0);
console.log(gerade.next().value);
}
// Wichtig · Fallstricke
- Kompatibilität: Die Methode gehört zum Vorschlag „Explicit Resource Management“ (
using,Symbol.dispose,DisposableStack). Unterstützt wird sie in Chrome/Edge ab 134, Firefox ab 135 und Node.js ab 24. Safari unterstützt sie noch nicht. Für ältere Umgebungen brauchst du einen Transpiler (TypeScript 5.2+, Babel) und ein Polyfill (z. B.core-js). - Nicht gestartete Generatoren: Wurde
next()noch nie aufgerufen, springtreturn()sofort in den Endzustand. Der Generator-Rumpf wurde nie betreten, darum läuft auch keinfinally-Block. Aufräumcode steht also nur zur Verfügung, wenn der Generator schon läuft. - Bei for...of meist unnötig:
for...of, Destrukturierung und Spread schließen Iteratoren beim vorzeitigen Abbruch schon von selbst.usinglohnt sich vor allem bei manuellernext()-Steuerung. - Kein Effekt ohne
return(): Array-, Map-, Set- und String-Iteratoren haben keinereturn()-Methode. Der Aufruf ändert bei ihnen nichts, und der Iterator liefert danach weiter Werte. - Ausnahmen: Wirft
return()einen Fehler, gibt[Symbol.dispose]()ihn weiter. Innerhalb vonusingkann dabei einSuppressedErrorentstehen, wenn der Block schon mit einem Fehler verlassen wurde. - Asynchrone Iteratoren: Für Async-Generatoren gibt es stattdessen
AsyncIterator.prototype[Symbol.asyncDispose](), das zusammen mitawait usingverwendet wird.