Signatur
Beschreibung
defer() legt eine Rückruffunktion auf einen AsyncDisposableStack. Wird der Stack entsorgt, etwa durch await stack.disposeAsync() oder am Blockende einer await using-Deklaration, ruft er die Funktion auf und wartet ihr Ergebnis mit await ab. Die Funktion kann ein Promise zurückgeben, muss es aber nicht.
Die Methode eignet sich für Aufräumarbeiten, die nicht an eine bestimmte Ressource gebunden sind: Logeinträge schreiben, Zwischenspeicher leeren, temporäre Dateien löschen oder globale Zustände zurücksetzen. Im Unterschied zu use() und adopt() braucht defer() keinen Wert. Die Funktion wird ohne Argumente aufgerufen.
Alle registrierten Aufräumfunktionen laufen nach dem LIFO-Prinzip (last in, first out): Was zuletzt registriert wurde, wird zuerst ausgeführt. So werden abhängige Ressourcen in der richtigen Reihenfolge freigegeben. Die Funktionen laufen nacheinander. Die nächste startet erst, wenn das Promise der vorherigen erfüllt ist.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $onDisposeAsync Pflicht | () => void | Promise<void> | Funktion, die beim Entsorgen des Stacks ohne Argumente aufgerufen wird. Gibt sie ein Promise zurück, wird es abgewartet, bevor die nächste Aufräumfunktion läuft. |
Rückgabewert
Beispiele
Grundlagen: Aufräumreihenfolge (LIFO)
const run = async () => {
const stack = new AsyncDisposableStack();
stack.defer(async () => {
await new Promise((r) => setTimeout(r, 50));
console.log('Aufräumen 1');
});
stack.defer(() => console.log('Aufräumen 2'));
console.log('Arbeit erledigt');
await stack.disposeAsync();
console.log('Stack entsorgt:', stack.disposed);
};
run();
Mit await using: temporäre Datei automatisch löschen (Node.js)
import { writeFile, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const processReport = async (content) => {
await using cleanup = new AsyncDisposableStack();
const file = join(tmpdir(), `report-${Date.now()}.txt`);
await writeFile(file, content);
// Wird auch bei einer Ausnahme im Block ausgeführt
cleanup.defer(async () => {
await rm(file, { force: true });
console.log('Temporäre Datei gelöscht');
});
console.log('Verarbeite', file);
// ... weitere Arbeit mit der Datei
};
await processReport('Umsatz Q1: 42.000 €');
Ressourcen sicher übergeben mit move()
const openConnection = async () => {
await using stack = new AsyncDisposableStack();
const conn = { id: 7, close: async () => console.log('Verbindung 7 geschlossen') };
stack.defer(() => conn.close());
// Schlägt hier etwas fehl, wird conn automatisch geschlossen.
// Bei Erfolg übernimmt der Aufrufer die Verantwortung:
const owned = stack.move();
return { conn, [Symbol.asyncDispose]: () => owned.disposeAsync() };
};
{
await using handle = await openConnection();
console.log('Nutze Verbindung', handle.conn.id);
}
// Wichtig · Fallstricke
- Funktion statt Aufruf übergeben:
stack.defer(conn.close())ruftclosesofort auf. Richtig iststack.defer(() => conn.close()). Ist der Wert keine Funktion, wirft die Methode einenTypeError. - Bereits entsorgter Stack: Wurde der Stack schon entsorgt (
stack.disposed === true), wirftdefer()einenReferenceError. Das gilt auch nachmove(). - Fehlerbehandlung: Wirft eine Aufräumfunktion einen Fehler, laufen die übrigen trotzdem. Mehrere Fehler werden in einem
SuppressedErrorzusammengefasst, unddisposeAsync()lehnt mit diesem Fehler ab. - Kein
this, keine Argumente: Die Funktion wird ohne Argumente aufgerufen. Wenn die Aufräumlogik den Ressourcenwert braucht, istadopt(value, onDispose)passender. - Kompatibilität: Die Methode gehört zum Proposal „Explicit Resource Management“ und ist recht neu. Unterstützt wird sie in Chromium 134+, Firefox 141+ und Node.js 24+, Safari fehlt bislang. Für ältere Umgebungen gibt es Polyfills, etwa
core-js, oder die Transpilation über TypeScript 5.2+ bzw. Babel. Die Syntaxawait usingmuss zusätzlich unterstützt oder transpiliert werden.