[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/await_using [Back]  [Original]

await using - JavaScript | MDN

Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.

View in English Always switch to English

await using

Eingeschrnkt verfgbar

Diese Funktion ist nicht Baseline, da sie in einigen der am weitesten verbreiteten Browser nicht funktioniert.

Want more browser support for this feature? Tell us why.

Die await using-Deklaration deklariert lokale Variablen mit Blockumfang, die asynchron entsorgt werden. Wie const mssen Variablen, die mit await using deklariert wurden, initialisiert werden und knnen nicht neu zugewiesen werden. Der Wert der Variablen muss entweder null, undefined oder ein Objekt sein, das ber eine [Symbol.asyncDispose]() oder [Symbol.dispose]()-Methode verfgt. Wenn die Variable auer Geltungsbereich gert, wird die Methode [Symbol.asyncDispose]() oder [Symbol.dispose]() des Objekts aufgerufen und erwartet, um sicherzustellen, dass Ressourcen freigegeben werden.

In diesem Artikel

Syntax

js
await using name1 = value1;
await using name1 = value1, name2 = value2;
await using name1 = value1, name2 = value2, /* , */ nameN = valueN;
nameN

Der Name der zu deklarierenden Variablen. Jede muss ein legaler JavaScript-Bezeichner sein und kein Destructuring-Bindungsmuster.

valueN

Initialwert der Variablen. Es kann jeder legale Ausdruck sein, aber sein Wert muss entweder null, undefined oder ein Objekt mit einer [Symbol.asyncDispose]() oder [Symbol.dispose]()-Methode sein.

Beschreibung

Diese Deklaration kann nur dort verwendet werden, wo sowohl await als auch using verwendet werden knnen, dazu gehren:

  • Innerhalb eines Blocks (wenn sich der Block auch in einem asynchronen Kontext befindet)
  • Innerhalb eines async functions oder async-Generator-Funktionskrpers
  • Auf oberster Ebene eines Moduls
  • In der Initialisierung einer for, for...of (wenn die for-Schleife sich auch in einem asynchronen Kontext befindet) oder for await...of-Schleife

Ein await using deklariert eine asynchron entbehrliche Ressource, die an die Lebensdauer des Variablenbereichs (Block, Funktion, Modul, etc.) gebunden ist. Wenn der Bereich beendet wird, wird die Ressource asynchron entsorgt. Die Syntax mag etwas verwirrend sein, da await keinen Wartungseffekt hat, wenn die Variable zuerst deklariert wird, sondern nur, wenn die Variable auer Geltungsbereich gert.

Wenn eine Variable zuerst deklariert wird und ihr Wert nicht null ist, wird ein Disposer vom Objekt abgerufen. Die [Symbol.asyncDispose]-Eigenschaft wird zuerst versucht und fllt auf [Symbol.dispose] zurck, wenn [Symbol.asyncDispose] undefined ist. Wenn keine der beiden Eigenschaften eine Funktion enthlt, wird ein TypeError ausgelst. Bemerkenswert ist, dass die [Symbol.dispose]()-Methode in eine Funktion eingeschlossen wird, die aussieht wie async () => { object[Symbol.dispose](); }, was bedeutet, dass, wenn sie ein Versprechen zurckgibt, dieses Versprechen nicht erwartet wird. Dieser Disposer wird im Bereich gespeichert.

Wenn die Variable auer Geltungsbereich gert, wird der Disposer aufgerufen und erwartet. Wenn der Bereich mehrere using- oder await using-Deklarationen enthlt, werden alle Disposer in umgekehrter Reihenfolge ihrer Deklaration sequenziell ausgefhrt, unabhngig von der Art der Deklaration. Alle Disposer werden garantierterweise ausgefhrt (hnlich dem finally-Block in try...catch...finally). Alle whrend der Entsorgung ausgelsten Fehler, einschlielich des initialen Fehlers, der den Skope-Verlust verursachte (falls zutreffend), werden alle innerhalb eines SuppressedError aggregiert, wobei jede frhere Ausnahme die Eigenschaft suppressed und die sptere Ausnahme die Eigenschaft error ist. Dieser SuppressedError wird nach Abschluss der Entsorgung ausgelst.

Die Variable darf den Wert null oder undefined haben, sodass die Ressource optional vorhanden sein kann. Solange eine await using-Variable in diesem Bereich deklariert wird, wird mindestens ein await beim Verlassen des Bereichs garantiert, auch wenn die Variable tatschlich den Wert null oder undefined hat. Dies verhindert, dass die Entsorgung synchron erfolgt und verursacht zeitliche Probleme (siehe Kontrollflusseffekte von await).

await using bindet das Ressourcenmanagement an lexikalische Bereiche, was sowohl bequem als auch manchmal verwirrend ist. Schauen Sie sich unten einige Beispiele an, in denen es mglicherweise nicht so funktioniert, wie Sie es erwarten. Wenn Sie die Entsorgung von Ressourcen manuell verwalten mchten, whrend Sie die gleichen Fehlerbehandlungsgarantien beibehalten, knnen Sie stattdessen AsyncDisposableStack verwenden.

Beispiele

Sie sollten auch using fr weitere Beispiele berprfen, insbesondere einige allgemeine Vorbehalte in Bezug auf das bereichsbasierte Ressourcenmanagement.

Grundlegende Verwendung

Normalerweise verwenden Sie await using auf einigen bibliotheksbereitgestellten Ressourcen, die bereits das asynchrone Entsorgungsprotokoll implementieren. Zum Beispiel ist das Node.js FileHandle asynchron entsorgbar:

js
import fs from "node:fs/promises";

async function example() {
  await using file = await fs.open("example.txt", "r");
  console.log(await file.read());
  // Before `file` goes out of scope, it is disposed by calling `file[Symbol.asyncDispose]()` and awaited.
}

Beachten Sie, dass es zwei await-Operationen in der Deklaration fr file gibt, die unterschiedliche Dinge tun und beide notwendig sind. await fs.open() bewirkt ein Warten whrend der Erwerbung: es wartet darauf, dass die Datei geffnet wird und entpackt das zurckgegebene Versprechen in ein FileHandle-Objekt. await using file bewirkt ein Warten whrend der Entsorgung: es sorgt dafr, dass file asynchron entsorgt wird, wenn die Variable auer Geltungsbereich gert.

await using mit for await...of

Es ist sehr einfach, die folgenden drei Syntaxen zu verwechseln:

  • for await (using x of y) { ... }
  • for (await using x of y) { ... }
  • for (using x of await y) { ... }

Es kann noch verwirrender sein zu wissen, dass sie zusammen verwendet werden knnen.

js
for await (await using x of await y) {
  // ...
}

Zuerst macht await y das, was Sie erwarten: wir await das Versprechen y, welches erwartet wird, um sich in ein Objekt aufzulsen, das wir durchlaufen. Lassen Sie uns diese Variante beiseitelegen.

Die for await...of-Schleife erfordert, dass das Objekt y ein asynchroner Iterierbar ist. Das bedeutet, dass das Objekt eine [Symbol.asyncIterator]-Methode haben muss, die einen asynchronen Iterator zurckgibt, dessen next()-Methode ein Versprechen zurckgibt, das das Ergebnis darstellt. Dies ist der Fall, wenn der Iterator nicht wei, was der nchste Wert ist oder sogar, ob es schon fertig ist, bis eine asynchrone Operation abgeschlossen ist.

Andererseits verlangt die await using x-Syntax, dass das Objekt x, das aus dem Iterator stammt, ein asynchron entsorgbar ist. Das bedeutet, dass das Objekt eine [Symbol.asyncDispose]-Methode haben muss, die ein Versprechen zurckgibt, das die Entsorgungsoperation darstellt. Dies ist ein separates Anliegen vom eigentlichen Iterationsvorgang und wird nur aufgerufen, wenn die Variable x auer Geltungsbereich gert.

Mit anderen Worten, alle folgenden vier Kombinationen sind gltig und tun unterschiedliche Dinge:

  • for (using x of y): y wird synchron durchlaufen und liefert ein Ergebnis nach dem anderen, das synchron entsorgt werden kann.
  • for await (using x of y): y wird asynchron durchlaufen und liefert ein Ergebnis nach dem anderen, nachdem gewartet wird, aber der Ergebniswert kann synchron entsorgt werden.
  • for (await using x of y): y wird synchron durchlaufen und liefert ein Ergebnis nach dem anderen, aber der Ergebniswert kann nur asynchron entsorgt werden.
  • for await (await using x of y): y wird asynchron durchlaufen und liefert ein Ergebnis nach dem anderen, nachdem gewartet wird, und der Ergebniswert kann nur asynchron entsorgt werden.

Unten erstellen wir einige fiktive Werte von y, um ihre Anwendungsflle zu demonstrieren. Fr asynchrone APIs basiert unser Code auf dem Node.js fs/promises-Modul.

js
const syncIterableOfSyncDisposables = [
  stream1.getReader(),
  stream2.getReader(),
];
for (using reader of syncIterableOfSyncDisposables) {
  console.log(reader.read());
}
js
async function* requestMany(urls) {
  for (const url of urls) {
    const res = await fetch(url);
    yield res.body.getReader();
  }
}
const asyncIterableOfSyncDisposables = requestMany([
  "https://example.com",
  "https://example.org",
]);
for await (using reader of asyncIterableOfSyncDisposables) {
  console.log(reader.read());
}
js
const syncIterableOfAsyncDisposables = await Promise.all(
  fs.globSync("*.txt").map((path) => fs.open(path, "r")),
);
for (await using file of syncIterableOfAsyncDisposables) {
  console.log(await file.read());
}
js
async function* globHandles(pattern) {
  for await (const path of fs.glob(pattern)) {
    yield await fs.open(path, "r");
  }
}
const asyncIterableOfAsyncDisposables = globHandles("*.txt");
for await (await using file of asyncIterableOfAsyncDisposables) {
  console.log(await file.read());
}

Implizites Warten beim Beenden des Geltungsbereichs

Sobald ein await using in einem Geltungsbereich deklariert wird, wird der Bereich immer ein await beim Beenden haben, selbst wenn die Variable null oder undefined ist. Dies stellt eine stabile Ausfhrungsreihenfolge und Fehlerbehandlung sicher. Die Beispiele unter Kontrollflusseffekte von await enthalten mehr Details dazu.

Im Beispiel unten lst der example()-Aufruf unten erst eine Takt spter auf, aufgrund eines impliziten await, wenn die Funktion zurckkehrt.

js
async function example() {
  await using nothing = null;
  console.log("Example call");
}

example().then(() => console.log("Example done"));
Promise.resolve().then(() => console.log("Microtask done"));
// Output:
// Example call
// Microtask done
// Example done

Betrachten Sie den gleichen Code, aber mit einem synchronen using stattdessen. Dieses Mal wird der example()-Aufruf sofort aufgelst, sodass die beiden then()-Handler im gleichen Takt aufgerufen werden.

js
async function example() {
  using nothing = null;
  console.log("Example call");
}

example().then(() => console.log("Example done"));
Promise.resolve().then(() => console.log("Microtask done"));
// Output:
// Example call
// Example done
// Microtask done

Fr ein realistischeres Beispiel betrachten Sie zwei gleichzeitige Aufrufe einer Funktion:

js
class Resource {
  #name;
  constructor(name) {
    this.#name = name;
  }
  async [Symbol.asyncDispose]() {
    console.log(`Disposing resource ${this.#name}`);
  }
}

async function example(id, createOptionalResource) {
  await using required = new Resource(`required ${id}`);
  await using optional = createOptionalResource
    ? new Resource("optional")
    : null;
  await using another = new Resource(`another ${id}`);
}

example(1, true);
example(2, false);
// Output:
// Disposing resource another 1
// Disposing resource another 2
// Disposing resource optional
// Disposing resource required 1
// Disposing resource required 2

Wie Sie sehen, wird die Ressource required 2 im gleichen Takt wie required 1 entsorgt. Wenn die optional-Ressource kein redundantes await verursacht htte, wre required 2 frher entsorgt worden, was gleichzeitig mit optional wre.

Spezifikationen

Spezifikation
ECMAScript Async Explicit Resource Management
# prod-AwaitUsingDeclaration

Browser-Kompatibilitt

Siehe auch


Web Proxy Viewer  |  New URL  |  Original Page