Start · Sprachen · JavaScript · Referenz · Symbol.asyncDispose

Symbol.asyncDispose

Eigenschaft

Wohlbekanntes Symbol, über das ein Objekt eine asynchrone Aufräummethode festlegt, die bei <code>await using</code> am Ende des Blocks automatisch aufgerufen wird.

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

Signatur

Symbol.asyncDispose

Beschreibung

Symbol.asyncDispose ist ein wohlbekanntes Symbol aus dem Vorschlag Explicit Resource Management. Ein Objekt, das unter diesem Symbol eine Methode hat, gilt als asynchron entsorgbar (Protokoll AsyncDisposable). Die Methode gibt normalerweise ein Promise zurück und räumt die Ressource auf, z. B. durch Schließen einer Datenbankverbindung, eines Datei-Handles oder eines Netzwerk-Streams.

Richtig nützlich wird das Symbol zusammen mit der Deklaration await using: Verlässt der Programmfluss den umgebenden Block, egal ob regulär, über return oder durch eine geworfene Ausnahme, ruft die Laufzeit obj[Symbol.asyncDispose]() auf und wartet auf das Ergebnis. Mehrere Ressourcen werden in umgekehrter Deklarationsreihenfolge freigegeben. Damit fallen die sonst nötigen und fehleranfälligen try/finally-Konstrukte weg.

Hat ein Objekt keine Methode [Symbol.asyncDispose], greift await using ersatzweise auf [Symbol.dispose] zurück. Für mehrere oder dynamisch hinzukommende Ressourcen gibt es AsyncDisposableStack. Die Eigenschaft selbst ist nicht beschreibbar, nicht aufzählbar und nicht konfigurierbar.

Beispiele

Eigene asynchron entsorgbare Ressource mit await using

class DbConnection {
  constructor(name) {
    this.name = name;
    console.log(`${name}: verbunden`);
  }
  async query(sql) {
    return `Ergebnis von "${sql}"`;
  }
  async [Symbol.asyncDispose]() {
    // z. B. Verbindung sauber schließen
    await new Promise((r) => setTimeout(r, 50));
    console.log(`${this.name}: getrennt`);
  }
}

const main = async () => {
  await using db = new DbConnection('db1');
  console.log(await db.query('SELECT 1'));
  // Am Blockende wird db[Symbol.asyncDispose]() aufgerufen und abgewartet
};

await main();
console.log('fertig');
db1: verbunden Ergebnis von "SELECT 1" db1: getrennt fertig

Aufräumen auch bei Fehlern, in umgekehrter Reihenfolge

const resource = (name) => ({
  async [Symbol.asyncDispose]() {
    console.log(`${name} freigegeben`);
  },
});

const run = async () => {
  await using a = resource('A');
  await using b = resource('B');
  throw new Error('Abbruch');
};

try {
  await run();
} catch (err) {
  console.log('Gefangen:', err.message);
}
B freigegeben A freigegeben Gefangen: Abbruch

Manuelle Nutzung ohne await using (Fallback)

const handle = {
  open: true,
  async [Symbol.asyncDispose]() {
    this.open = false;
  },
};

try {
  console.log('Arbeite, offen:', handle.open);
} finally {
  // Protokoll direkt aufrufen, wenn die Syntax nicht verfügbar ist
  await handle[Symbol.asyncDispose]?.();
}
console.log('offen:', handle.open);
console.log(Symbol.asyncDispose.description);
Arbeite, offen: true offen: false Symbol.asyncDispose

Mehrere Ressourcen mit AsyncDisposableStack bündeln

const openTemp = (id) => ({
  id,
  async [Symbol.asyncDispose]() {
    console.log(`Temp ${id} gelöscht`);
  },
});

const process = async () => {
  await using stack = new AsyncDisposableStack();
  const files = [1, 2, 3].map((id) => stack.use(openTemp(id)));
  stack.defer(async () => console.log('Log-Eintrag geschrieben'));
  console.log(`${files.length} Dateien verarbeitet`);
};

await process();
3 Dateien verarbeitet Log-Eintrag geschrieben Temp 3 gelöscht Temp 2 gelöscht Temp 1 gelöscht

// Wichtig · Fallstricke

  • Kompatibilität: Symbol.asyncDispose und await using sind recht neu (Chromium 134+, Firefox 141+, Node.js 24+). In Safari fehlen sie noch. Node.js stellt das Symbol schon seit 18.18/20.4 bereit, die Syntax kam aber erst später. TypeScript unterstützt beides ab 5.2 (lib: \"esnext.disposable\"). Für ältere Umgebungen ist ein Polyfill nötig, z. B. core-js. Die Syntax selbst muss transpiliert werden.
  • await using geht nur dort, wo auch await erlaubt ist, also in async-Funktionen oder auf der obersten Ebene eines Moduls. Ein Einsatz auf oberster Ebene eines switch-case ohne Block ist nicht erlaubt.
  • Wirft die Aufräummethode einen Fehler, während schon ein anderer Fehler aktiv ist, fasst die Laufzeit beide in einem SuppressedError zusammen (error und suppressed).
  • Die Werte null und undefined sind bei await using erlaubt und werden übersprungen. Andere Werte ohne [Symbol.asyncDispose] oder [Symbol.dispose] lösen einen TypeError aus.
  • Die Aufräummethode sollte idempotent sein, also einen zweiten Aufruf ohne Fehler überstehen. Sie sollte nicht zu lange blockieren, denn das Verlassen des Blocks wartet auf sie.