Signatur
Beschreibung
Mit new DisposableStack() erzeugst du ein leeres DisposableStack-Objekt. Darin sammelst du Ressourcen und Aufräumfunktionen, die später gemeinsam freigegeben werden sollen, zum Beispiel Dateihandles, Sperren, Event-Listener oder Timer. Beim Aufruf von dispose() oder am Ende eines using-Blocks laufen alle registrierten Aufräumaktionen in umgekehrter Reihenfolge ab (LIFO, zuletzt hinzugefügt wird zuerst aufgeräumt).
Registriert wird über drei Methoden: use(value) für Objekte mit einer [Symbol.dispose]()-Methode, adopt(value, onDispose) für Werte ohne eigene Freigabelogik und defer(onDispose) für eine reine Aufräumfunktion. Mit move() überträgst du alle Einträge auf einen neuen Stapel. Das ist praktisch, wenn ein Konstruktor oder eine Fabrikfunktion Ressourcen erst dann an den Aufrufer übergeben soll, wenn alles geklappt hat.
Der Konstruktor erwartet keine Argumente und muss mit new aufgerufen werden. Weil DisposableStack selbst [Symbol.dispose] implementiert, lässt er sich direkt mit using deklarieren: using stack = new DisposableStack();. Für asynchrone Aufräumarbeiten gibt es das Gegenstück AsyncDisposableStack.
Rückgabewert
DisposableStack-Objekt, dessen disposed-Eigenschaft false ist.Beispiele
Stapel erzeugen und manuell freigeben
const stack = new DisposableStack();
stack.defer(() => console.log('Aufräumen: Verbindung schließen'));
stack.defer(() => console.log('Aufräumen: Cache leeren'));
console.log(stack.disposed);
stack.dispose();
console.log(stack.disposed);
Mit using automatisch aufräumen
const createTimer = (label) => {
const id = setInterval(() => {}, 1000);
console.log(`${label} gestartet`);
return { id, [Symbol.dispose]() { clearInterval(id); console.log(`${label} gestoppt`); } };
};
function runJob() {
using stack = new DisposableStack();
stack.use(createTimer('Timer A'));
stack.use(createTimer('Timer B'));
// adopt: Wert ohne eigenes Symbol.dispose
const controller = stack.adopt(new AbortController(), (c) => {
c.abort();
console.log('Controller abgebrochen');
});
console.log('Job läuft, Signal aktiv:', !controller.signal.aborted);
} // hier wird der Stapel automatisch freigegeben
runJob();
Ressourcen sicher übergeben mit move()
class Connection {
#stack;
constructor() {
using stack = new DisposableStack();
stack.defer(() => console.log('Socket geschlossen'));
stack.defer(() => console.log('Log-Datei geschlossen'));
// Schlägt hier etwas fehl, räumt using sofort alles auf.
// Klappt alles, übernimmt die Instanz die Ressourcen:
this.#stack = stack.move();
}
[Symbol.dispose]() {
this.#stack.dispose();
}
}
{
using conn = new Connection();
console.log('Verbindung in Benutzung');
}
// Wichtig · Fallstricke
- Kompatibilität: Das Feature ist neu (Explicit Resource Management, ES2026). Chrome/Edge 134+, Firefox 134+ und Node.js 24+ unterstützen es, Safari noch nicht. Bei älteren Umgebungen hilft ein Polyfill (z. B.
core-js). Dieusing-Syntax braucht zusätzlich Unterstützung durch Engine oder Transpiler (TypeScript 5.2+, Babel). - Ohne
newaufgerufen wirftDisposableStack()einenTypeError. - Nach
dispose()odermove()ist der Stapel verbraucht. Weitere Aufrufe vonuse(),adopt(),defer()odermove()werfen einenReferenceError. Ein erneutesdispose()bewirkt nichts. - Werfen mehrere Aufräumfunktionen Fehler, werden sie in einem
SuppressedErrorverschachtelt. Die übrigen Aufräumaktionen laufen trotzdem weiter. use()akzeptiertnullundundefined(sie werden ignoriert). Andere Werte ohne[Symbol.dispose]führen zu einemTypeError.- Für Promise-basierte Aufräumarbeiten gibt es
AsyncDisposableStackzusammen mitawait using.DisposableStackwartet nicht auf zurückgegebene Promises.