Start · Sprachen · JavaScript · Referenz · DisposableStack.prototype[Symbol.dispose]()

DisposableStack.prototype[Symbol.dispose]()

Methode

Gibt alle auf dem <code>DisposableStack</code> registrierten Ressourcen in umgekehrter Reihenfolge frei und setzt damit das Disposable-Protokoll für <code>using</code> um.

seit JavaScript Explicit Resource Management (ES2026); Chrome 134+ Kategorie: method-property

Signatur

DisposableStack.prototype[Symbol.dispose]()

Beschreibung

Die Methode [Symbol.dispose]() setzt das Disposable-Protokoll für DisposableStack-Instanzen um. Deshalb kann ein Stack direkt mit using (oder await using) deklariert werden: Verlässt das Programm den Block, ruft die Laufzeit automatisch stack[Symbol.dispose]() auf. Das passiert auch dann, wenn im Block ein Fehler geworfen wird.

Es handelt sich um dasselbe Funktionsobjekt wie DisposableStack.prototype.dispose. Beim Aufruf werden alle Ressourcen, die mit use(), adopt() oder defer() registriert wurden, in umgekehrter Reihenfolge (LIFO) freigegeben. Danach gilt der Stack als entsorgt (disposed === true). Weitere Aufrufe bewirken nichts.

Wirft eine Freigabe-Funktion einen Fehler, werden die übrigen Ressourcen trotzdem freigegeben. Mehrere Fehler werden zu einem SuppressedError verkettet, der am Ende geworfen wird. In error steht der zuletzt aufgetretene Fehler, in suppressed der davor aufgetretene.

Einsatzgebiet: mehrere Ressourcen (Dateihandles, Sperren, Listener, Timer) gebündelt und ausnahmesicher aufräumen, ohne verschachtelte try…finally-Blöcke.

Rückgabewert

Typ
undefined
Beschreibung
Die Methode gibt nichts zurück. Wenn beim Freigeben Fehler auftreten, wird ein Fehler geworfen (bei mehreren Fehlern ein SuppressedError).

Beispiele

Automatische Freigabe mit using

{
  using stack = new DisposableStack();
  stack.defer(() => console.log("Verbindung geschlossen"));
  stack.defer(() => console.log("Datei geschlossen"));
  console.log("Arbeite...");
} // hier ruft die Laufzeit stack[Symbol.dispose]() auf
Arbeite... Datei geschlossen Verbindung geschlossen

Manueller Aufruf – mehrfach aufrufbar, nur einmal wirksam

console.log(DisposableStack.prototype[Symbol.dispose] === DisposableStack.prototype.dispose);

const stack = new DisposableStack();
stack.use({
  [Symbol.dispose]() { console.log("Ressource freigegeben"); }
});

stack[Symbol.dispose]();
stack[Symbol.dispose](); // bewirkt nichts mehr
console.log(stack.disposed);
true Ressource freigegeben true

Fehler beim Freigeben werden zu SuppressedError verkettet

const stack = new DisposableStack();
stack.defer(() => { throw new Error("A"); });
stack.defer(() => { throw new Error("B"); });

try {
  stack[Symbol.dispose]();
} catch (e) {
  // B wird zuerst freigegeben, danach A
  console.log(e instanceof SuppressedError, e.error.message, e.suppressed.message);
}
true A B

Ressourcen einer Klasse bündeln und im eigenen Dispose freigeben

class Widget {
  #stack;
  constructor(el) {
    using stack = new DisposableStack();
    const onClick = () => console.log("Klick");
    el.addEventListener("click", onClick);
    stack.defer(() => el.removeEventListener("click", onClick));
    const id = setInterval(() => {}, 1000);
    stack.defer(() => clearInterval(id));
    // Erfolgreich aufgebaut: Ressourcen an die Instanz übertragen
    this.#stack = stack.move();
  }
  [Symbol.dispose]() {
    this.#stack[Symbol.dispose]();
  }
}

{
  using widget = new Widget(document.body);
  // ... Widget benutzen
} // Listener und Intervall werden entfernt

// Wichtig · Fallstricke

  • Kompatibilität: Explicit Resource Management ist neu (Chrome/Edge 134+, Firefox 134+, Node.js 24+). Safari unterstützt es noch nicht. Für ältere Umgebungen gibt es Polyfills (z. B. core-js) und Transpilierung mit TypeScript 5.2+ oder Babel.
  • using ist nur in Blöcken, Funktionen und auf oberster Ebene von Modulen erlaubt, nicht auf oberster Ebene klassischer Skripte.
  • Die Freigabe erfolgt synchron. Asynchrone Aufräumfunktionen werden nicht abgewartet – dafür AsyncDisposableStack mit await using verwenden.
  • Nach der Freigabe werfen use(), adopt(), defer() und move() einen ReferenceError. Mit disposed lässt sich der Zustand prüfen.
  • Ein Fehler in einer Aufräumfunktion bricht die Freigabe der übrigen Ressourcen nicht ab. Wer Fehler auswertet, sollte die Kette über SuppressedError.suppressed durchlaufen.
  • Wird die Methode auf einem Objekt aufgerufen, das kein DisposableStack ist, wird ein TypeError geworfen.