Start · Sprachen · JavaScript · Referenz · AsyncDisposableStack.prototype.defer()

AsyncDisposableStack.prototype.defer()

Methode

Registriert eine (asynchrone) Aufräumfunktion auf dem Stack, die beim Entsorgen in umgekehrter Reihenfolge aufgerufen und abgewartet wird.

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

Signatur

AsyncDisposableStack.prototype.defer(onDisposeAsync)

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

Typ
undefined
Beschreibung
Kein Rückgabewert. Die Funktion wird nur auf dem Stack registriert.

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();
Arbeit erledigt Aufräumen 2 Aufräumen 1 Stack entsorgt: true

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 €');
Verarbeite /tmp/report-1712345678901.txt Temporäre Datei gelöscht

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);
}
Nutze Verbindung 7 Verbindung 7 geschlossen

// Wichtig · Fallstricke

  • Funktion statt Aufruf übergeben: stack.defer(conn.close()) ruft close sofort auf. Richtig ist stack.defer(() => conn.close()). Ist der Wert keine Funktion, wirft die Methode einen TypeError.
  • Bereits entsorgter Stack: Wurde der Stack schon entsorgt (stack.disposed === true), wirft defer() einen ReferenceError. Das gilt auch nach move().
  • Fehlerbehandlung: Wirft eine Aufräumfunktion einen Fehler, laufen die übrigen trotzdem. Mehrere Fehler werden in einem SuppressedError zusammengefasst, und disposeAsync() lehnt mit diesem Fehler ab.
  • Kein this, keine Argumente: Die Funktion wird ohne Argumente aufgerufen. Wenn die Aufräumlogik den Ressourcenwert braucht, ist adopt(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 Syntax await using muss zusätzlich unterstützt oder transpiliert werden.