Signatur
Beschreibung
use() nimmt eine Ressource entgegen, die das asynchrone Entsorgungsprotokoll umsetzt, also eine Methode [Symbol.asyncDispose]() besitzt. Als Ersatz wird auch eine synchrone [Symbol.dispose]()-Methode akzeptiert. Die Ressource wird auf den Stapel gelegt und beim Aufruf von disposeAsync() oder am Ende eines await using-Blocks automatisch aufgeräumt.
Die Methode gibt den übergebenen Wert unverändert zurück. Deshalb kann man Erzeugung und Registrierung in einer Zeile schreiben: const conn = stack.use(await openConnection()). Das entspricht im Ergebnis einer await using-Deklaration. Der Unterschied: Ressourcen lassen sich so auch dynamisch, bedingt oder in Schleifen registrieren.
Die Entsorgung läuft in umgekehrter Reihenfolge (LIFO): Was zuletzt registriert wurde, wird zuerst aufgeräumt. Jede Entsorgung wird abgewartet, bevor die nächste startet. Werden die Werte null oder undefined übergeben, ignoriert use() sie stillschweigend und gibt sie zurück. So lassen sich optionale Ressourcen ohne zusätzliche Prüfung registrieren.
Ressourcen ohne Entsorgungsprotokoll registriert man mit adopt(). Reine Aufräum-Funktionen hängt man mit defer() an.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value Pflicht | AsyncDisposable | Disposable | null | undefined | Das Objekt, das registriert werden soll. Es muss eine Methode [Symbol.asyncDispose]() oder [Symbol.dispose]() besitzen. null und undefined werden ignoriert. |
Rückgabewert
value, unverändert. So lässt sich der Aufruf direkt in einer Zuweisung verwenden.Beispiele
Grundlegende Nutzung mit await using
const openFile = async (name) => {
console.log(`öffne ${name}`);
return {
name,
async [Symbol.asyncDispose]() {
await new Promise((r) => setTimeout(r, 10));
console.log(`schließe ${name}`);
},
};
};
const main = async () => {
await using stack = new AsyncDisposableStack();
const file = stack.use(await openFile('daten.txt'));
console.log(`arbeite mit ${file.name}`);
}; // hier wird stack.disposeAsync() automatisch abgewartet
await main();
Mehrere und optionale Ressourcen – Entsorgung in umgekehrter Reihenfolge
const resource = (id) => ({
id,
async [Symbol.asyncDispose]() {
console.log(`entsorge ${id}`);
},
});
const withCache = false;
const stack = new AsyncDisposableStack();
const db = stack.use(resource('db'));
const cache = stack.use(withCache ? resource('cache') : null); // null wird ignoriert
// Synchron entsorgbare Objekte werden ebenfalls akzeptiert
stack.use({ [Symbol.dispose]() { console.log('entsorge logger (sync)'); } });
console.log(db.id, cache);
await stack.disposeAsync();
console.log('disposed:', stack.disposed);
Fabrikfunktion: Ressourcen bei Fehlern aufräumen, bei Erfolg mit move() weitergeben
const connect = async (name) => ({
name,
async [Symbol.asyncDispose]() { console.log(`trenne ${name}`); },
});
const createService = async () => {
await using stack = new AsyncDisposableStack();
const db = stack.use(await connect('db'));
const queue = stack.use(await connect('queue'));
// Schlägt vor dieser Zeile etwas fehl, werden db und queue automatisch getrennt.
const owned = stack.move(); // Besitz übergeben, stack selbst entsorgt nichts mehr
return {
db,
queue,
[Symbol.asyncDispose]: () => owned.disposeAsync(),
};
};
{
await using service = await createService();
console.log('Dienst läuft mit', service.db.name, 'und', service.queue.name);
}
// Wichtig · Fallstricke
- TypeError: Ist
valueweder ein Objekt nochnulloderundefined, oder fehlt sowohl[Symbol.asyncDispose]als auch[Symbol.dispose], wirftuse()sofort einenTypeError. Für beliebige Werte nimmt man stattdessenadopt(). - ReferenceError: Wurde der Stapel bereits entsorgt (
stack.disposed === true, auch nachmove()), führt jeder weitere Aufruf vonuse()zu einemReferenceError. - Die Entsorgungsmethode wird schon beim Aufruf von
use()ausgelesen und gespeichert. Wird sie danach am Objekt ersetzt, hat das keine Wirkung mehr. - Werfen mehrere Entsorgungen einen Fehler, laufen trotzdem alle ab. Am Ende wird ein
SuppressedErrorgeworfen, der die Fehler verkettet. use()gibt kein Promise zurück und muss nicht mitawaitaufgerufen werden. Asynchron ist erstdisposeAsync().- Kompatibilität: Die Methode gehört zum neuen Sprachbestandteil „Explicit Resource Management“. Safari unterstützt sie noch nicht, ältere Umgebungen brauchen ein Polyfill (z. B. aus core-js). Die Syntax
await usingbraucht außerdem Unterstützung durch Transpiler oder Engine.