Start · Sprachen · JavaScript · Referenz · DisposableStack.prototype.dispose()

DisposableStack.prototype.dispose()

Methode

Entsorgt den Stapel, indem alle registrierten Disposer in umgekehrter Reihenfolge ihrer Registrierung aufgerufen werden (LIFO).

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

Signatur

DisposableStack.prototype.dispose()

Beschreibung

dispose() gibt alle Ressourcen frei, die über use(), adopt() oder defer() bei einem DisposableStack registriert wurden. Die Disposer laufen in umgekehrter Reihenfolge (LIFO): Was zuletzt registriert wurde, wird zuerst entsorgt. So werden abhängige Ressourcen sauber abgebaut, zum Beispiel erst die Transaktion und danach die Datenbankverbindung.

Die Methode ist identisch mit DisposableStack.prototype[Symbol.dispose](). Deshalb entsorgt eine Deklaration wie using stack = new DisposableStack() den Stapel am Blockende automatisch. Ein manueller Aufruf von dispose() ist dann sinnvoll, wenn es kein using gibt, etwa in älterem Code, in try…finally-Konstrukten oder wenn Sie den Zeitpunkt der Freigabe selbst bestimmen wollen.

Nach dem Aufruf steht disposed auf true. Ein zweiter Aufruf von dispose() bewirkt nichts. Die Methoden use(), adopt(), defer() und move() werfen danach einen ReferenceError.

Wirft ein Disposer einen Fehler, werden die übrigen Disposer trotzdem aufgerufen. Am Ende wird der Fehler weitergeworfen. Bei mehreren Fehlern werden sie zu einem SuppressedError verschachtelt.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert (undefined). Kann aber einen Fehler werfen, wenn ein Disposer fehlschlägt.

Beispiele

LIFO-Reihenfolge beim Aufräumen

const stack = new DisposableStack();

stack.defer(() => console.log('Verbindung geschlossen'));
stack.defer(() => console.log('Transaktion beendet'));
stack.defer(() => console.log('Cache geleert'));

stack.dispose();
console.log('disposed:', stack.disposed);

// Zweiter Aufruf bewirkt nichts
stack.dispose();
Cache geleert Transaktion beendet Verbindung geschlossen disposed: true

Manuelle Entsorgung mit try…finally (ohne using)

const openFile = (name) => ({
  name,
  [Symbol.dispose]() {
    console.log(`${name} geschlossen`);
  },
});

const processFiles = () => {
  const stack = new DisposableStack();
  try {
    const a = stack.use(openFile('eingabe.csv'));
    const b = stack.use(openFile('ausgabe.csv'));
    console.log(`Verarbeite ${a.name} -> ${b.name}`);
  } finally {
    stack.dispose();
  }
};

processFiles();
Verarbeite eingabe.csv -> ausgabe.csv ausgabe.csv geschlossen eingabe.csv geschlossen

Fehlerbehandlung: SuppressedError bei mehreren Fehlern

const stack = new DisposableStack();

stack.defer(() => { throw new Error('Fehler A'); });
stack.defer(() => console.log('läuft trotzdem'));
stack.defer(() => { throw new Error('Fehler B'); });

try {
  stack.dispose();
} catch (err) {
  console.log(err instanceof SuppressedError);
  console.log(err.error.message);      // zuletzt geworfener Fehler
  console.log(err.suppressed.message); // zuvor geworfener Fehler
}
läuft trotzdem true Fehler A Fehler B

Ressourcen nach Fehler im Konstruktor wieder freigeben

class Service {
  #stack;
  constructor(fail = false) {
    const stack = new DisposableStack();
    try {
      stack.defer(() => console.log('Socket freigegeben'));
      if (fail) throw new Error('Initialisierung fehlgeschlagen');
      stack.defer(() => console.log('Timer gestoppt'));
      this.#stack = stack.move(); // Besitz übernehmen
    } finally {
      stack.dispose(); // wirkt nur, wenn move() nicht erreicht wurde
    }
  }
  dispose() {
    this.#stack.dispose();
  }
}

try { new Service(true); } catch (e) { console.log(e.message); }
const s = new Service();
s.dispose();
Socket freigegeben Initialisierung fehlgeschlagen Timer gestoppt Socket freigegeben

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Die Methode gehört zum Vorschlag „Explicit Resource Management“. Sie wird in Chrome/Edge ab 134, Firefox ab 134 und Node.js ab 24 unterstützt. Safari unterstützt sie noch nicht. Für ältere Umgebungen gibt es Polyfills, z. B. core-js.
  • Nur synchron: dispose() wartet nicht auf Promises. Gibt ein Disposer ein Promise zurück, wird es ignoriert. Für asynchrone Freigaben verwenden Sie AsyncDisposableStack mit disposeAsync().
  • Fehler werden nicht verschluckt: Alle Disposer laufen, aber am Ende wird ein Fehler geworfen. Bei einem einzigen Fehler ist es genau dieser Fehler, bei mehreren ein verschachtelter SuppressedError. Die Eigenschaft error enthält den zuletzt geworfenen Fehler, suppressed die vorherigen.
  • Nach der Entsorgung gesperrt: use(), adopt(), defer() und move() werfen dann einen ReferenceError. Weitere Aufrufe von dispose() bewirken nichts und sind unschädlich.
  • Nach move() gilt der ursprüngliche Stapel bereits als entsorgt. Ein anschließender Aufruf von dispose() ruft also keine Disposer mehr auf.