Start · Sprachen · JavaScript · Referenz · await using

await using

Anweisung

Deklariert eine blockweit gültige Variable, deren <code>Symbol.asyncDispose</code>-Methode am Ende des Blocks automatisch mit <code>await</code> aufgerufen wird.

seit JavaScript ES2025 (Stage 3 → ES2025; V8 ab Chrome 134, Firefo Kategorie: syntax

Signatur

await using identifier = expression

Beschreibung

await using ist Teil des Explicit Resource Management-Vorschlags (TC39) und die asynchrone Variante von using. Ähnlich wie try…finally stellt es sicher, dass eine Ressource — z. B. eine Datenbankverbindung, ein Datei-Handle oder ein Stream — am Ende eines Blocks zuverlässig freigegeben wird, auch wenn eine Ausnahme geworfen wird.

Die zugewiesene Ressource muss eine Methode unter dem Symbol Symbol.asyncDispose implementieren. Beim Verlassen des Blocks (regulär oder durch eine Exception) ruft die JavaScript-Runtime diese Methode automatisch mit await auf. await using darf daher nur in async-Funktionen oder im Top-Level-Modul verwendet werden.

Mehrere await using-Deklarationen im selben Block werden in umgekehrter Reihenfolge ihrer Deklaration entsorgt (LIFO — Last In, First Out). Wirft die Dispose-Methode ihrerseits einen Fehler, wird dieser über den SuppressedError-Mechanismus mit einem eventuell bereits vorhandenen Fehler kombiniert.

await using kann zusammen mit using (synchron) im selben Block gemischt werden. Zum Erstellen kompatibler Objekte empfiehlt sich das Hilfsobjekt AsyncDisposableStack oder die Kombination von Symbol.dispose und Symbol.asyncDispose.

Parameter

Name Typ Default Beschreibung
$identifier Pflicht string Name der Variablen, über die die Ressource im Block erreichbar ist. Destrukturierung ist nicht erlaubt — es muss ein einfacher Bezeichner sein.
$expression Pflicht object | null | undefined Ein Ausdruck, dessen Ergebnis entweder null/undefined ist (wird dann ignoriert) oder ein Objekt mit einer [Symbol.asyncDispose]()-Methode (und optional [Symbol.dispose]()).

Rückgabewert

Typ
void
Beschreibung
await using ist eine Deklarationsanweisung und hat keinen Rückgabewert.

Beispiele

Datenbankverbindung automatisch schließen

// Simulierte async-Datenbankverbindung mit Symbol.asyncDispose
function openConnection(dsn) {
  console.log(`Verbindung zu ${dsn} geöffnet`);
  return {
    async query(sql) {
      console.log(`Query: ${sql}`);
      return [{ id: 1, name: 'Alice' }];
    },
    async [Symbol.asyncDispose]() {
      console.log('Verbindung asynchron geschlossen');
      // z. B. await connection.end()
    }
  };
}

async function loadUsers() {
  await using conn = openConnection('postgres://localhost/mydb');
  const users = await conn.query('SELECT * FROM users');
  console.log('Benutzer:', users);
  // Symbol.asyncDispose wird hier automatisch aufgerufen
}

await loadUsers();
// Ausgabe:
// Verbindung zu postgres://localhost/mydb geöffnet
// Query: SELECT * FROM users
// Benutzer: [{ id: 1, name: 'Alice' }]
// Verbindung asynchron geschlossen
Verbindung zu postgres://localhost/mydb geöffnet Query: SELECT * FROM users Benutzer: [{ id: 1, name: 'Alice' }] Verbindung asynchron geschlossen

LIFO-Reihenfolge und Fehlerbehandlung mit SuppressedError

function makeResource(name) {
  console.log(`${name}: geöffnet`);
  return {
    async [Symbol.asyncDispose]() {
      console.log(`${name}: geschlossen`);
    }
  };
}

async function demo() {
  try {
    await using a = makeResource('A');
    await using b = makeResource('B');
    await using c = makeResource('C');
    console.log('Arbeit wird erledigt...');
    throw new Error('Fehler während der Arbeit');
  } catch (err) {
    // err ist ggf. ein SuppressedError, wenn auch Dispose fehlschlug
    console.error('Gefangener Fehler:', err.message);
  }
}

await demo();
// Ressourcen werden in umgekehrter Reihenfolge geschlossen: C → B → A
A: geöffnet B: geöffnet C: geöffnet Arbeit wird erledigt... C: geschlossen B: geschlossen A: geschlossen Gefangener Fehler: Fehler während der Arbeit

AsyncDisposableStack für dynamisch gesammelte Ressourcen

async function processFiles(paths) {
  await using stack = new AsyncDisposableStack();

  const handles = paths.map(p => {
    const handle = {
      path: p,
      async [Symbol.asyncDispose]() {
        console.log(`Handle für ${p} freigegeben`);
      }
    };
    // Ressource beim Stack registrieren
    stack.use(handle);
    return handle;
  });

  for (const h of handles) {
    console.log(`Verarbeite: ${h.path}`);
  }
  // Am Ende des Blocks: alle Handles in umgekehrter Reihenfolge freigeben
}

await processFiles(['a.txt', 'b.txt', 'c.txt']);
Verarbeite: a.txt Verarbeite: b.txt Verarbeite: c.txt Handle für c.txt freigegeben Handle für b.txt freigegeben Handle für a.txt freigegeben

// Wichtig · Fallstricke

Browserunterstützung (Stand 2025): V8-basierte Browser ab Chrome 134 und Node.js ab Version 22 unterstützen await using nativ. Firefox und Safari befinden sich noch in der Implementierungsphase. Für ältere Zielumgebungen ist ein Transpiler (z. B. Babel mit dem Proposal-Plugin oder TypeScript ≥ 5.2) erforderlich.

Nur in async-Kontext: Da die Dispose-Methode intern mit await aufgerufen wird, ist await using außerhalb von async-Funktionen oder Top-Level-Modulen ein Syntaxfehler.

SuppressedError: Wirft sowohl der Blockrumpf als auch eine Dispose-Methode eine Exception, werden beide Fehler in einem SuppressedError-Objekt gebündelt (error = primärer Fehler, suppressed = unterdrückter Fehler). Dieser Mechanismus verhindert, dass Dispose-Fehler den ursprünglichen Fehler stillschweigend überschreiben.

Null/Undefined erlaubt: Wird null oder undefined zugewiesen, unternimmt die Runtime beim Verlassen des Blocks nichts. Objekte ohne [Symbol.asyncDispose], aber mit [Symbol.dispose], werden synchron entsorgt.