Movatterモバイル変換


[0]ホーム

URL:


  1. Web
  2. JavaScript
  3. JavaScript-Referenz
  4. Anweisungen und Deklarationen
  5. await using

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

View in EnglishAlways switch to English

await using

Limited availability

This feature is not Baseline because it does not work in some of the most widely-used browsers.

Dieawait using-Deklaration deklariert lokale Variablen mit Blockumfang, dieasynchron entsorgt werden. Wieconst müssen Variablen, die mitawait using deklariert wurden, initialisiert werden und können nicht neu zugewiesen werden. Der Wert der Variablen muss entwedernull,undefined oder ein Objekt sein, das über eine[Symbol.asyncDispose]() oder[Symbol.dispose]()-Methode verfügt. Wenn die Variable außer Geltungsbereich gerät, wird die Methode[Symbol.asyncDispose]() oder[Symbol.dispose]() des Objekts aufgerufen und erwartet, um sicherzustellen, dass Ressourcen freigegeben werden.

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 undkeinDestructuring-Bindungsmuster.

valueN

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

Beschreibung

Diese Deklaration kann nur dort verwendet werden, wo sowohlawait als auchusing verwendet werden können, dazu gehören:

  • Innerhalb einesBlocks (wenn sich der Block auch in einem asynchronen Kontext befindet)
  • Innerhalb einesasync functions oder async-Generator-Funktionskörpers
  • Auf oberster Ebene einesModuls
  • In der Initialisierung einerfor,for...of (wenn diefor-Schleife sich auch in einem asynchronen Kontext befindet) oderfor await...of-Schleife

Einawait 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, daawait keinen Wartungseffekt hat, wenn die Variable zuerst deklariert wird, sondern nur, wenn die Variable außer Geltungsbereich gerät.

Wenn eine Variable zuerst deklariert wird und ihr Wert nicht null ist, wird einDisposer vom Objekt abgerufen. Die[Symbol.asyncDispose]-Eigenschaft wird zuerst versucht und fällt auf[Symbol.dispose] zurück, wenn[Symbol.asyncDispose]undefined ist. Wenn keine der beiden Eigenschaften eine Funktion enthält, wird einTypeError ausgelöst. Bemerkenswert ist, dass die[Symbol.dispose]()-Methode in eine Funktion eingeschlossen wird, die aussieht wieasync () => { object[Symbol.dispose](); }, was bedeutet, dass, wenn sie ein Versprechen zurückgibt, dieses Versprechennicht erwartet wird. Dieser Disposer wird im Bereich gespeichert.

Wenn die Variable außer Geltungsbereich gerät, wird der Disposer aufgerufen und erwartet. Wenn der Bereich mehrereusing- oderawait using-Deklarationen enthält, werden alle Disposer in umgekehrter Reihenfolge ihrer Deklaration sequenziell ausgeführt, unabhängig von der Art der Deklaration. Alle Disposer werden garantierterweise ausgeführt (ähnlich demfinally-Block intry...catch...finally). Alle während der Entsorgung ausgelösten Fehler, einschließlich des initialen Fehlers, der den Skope-Verlust verursachte (falls zutreffend), werden alle innerhalb einesSuppressedError aggregiert, wobei jede frühere Ausnahme die Eigenschaftsuppressed und die spätere Ausnahme die Eigenschafterror ist. DieserSuppressedError wird nach Abschluss der Entsorgung ausgelöst.

Die Variable darf den Wertnull oderundefined haben, sodass die Ressource optional vorhanden sein kann. Solange eineawait using-Variable in diesem Bereich deklariert wird, wird mindestens einawait beim Verlassen des Bereichs garantiert, auch wenn die Variable tatsächlich den Wertnull oderundefined hat. Dies verhindert, dass die Entsorgung synchron erfolgt und verursacht zeitliche Probleme (sieheKontrollflusseffekte vonawait).

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 möglicherweise nicht so funktioniert, wie Sie es erwarten. Wenn Sie die Entsorgung von Ressourcen manuell verwalten möchten, während Sie die gleichen Fehlerbehandlungsgarantien beibehalten, können Sie stattdessenAsyncDisposableStack verwenden.

Beispiele

Sie sollten auchusing für weitere Beispiele überprüfen, insbesondere einige allgemeine Vorbehalte in Bezug auf das bereichsbasierte Ressourcenmanagement.

Grundlegende Verwendung

Normalerweise verwenden Sieawait using auf einigen bibliotheksbereitgestellten Ressourcen, die bereits das asynchrone Entsorgungsprotokoll implementieren. Zum Beispiel ist das Node.jsFileHandle 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 zweiawait-Operationen in der Deklaration fürfile gibt, die unterschiedliche Dinge tun und beide notwendig sind.await fs.open() bewirkt ein Warten während derErwerbung: es wartet darauf, dass die Datei geöffnet wird und entpackt das zurückgegebene Versprechen in einFileHandle-Objekt.await using file bewirkt ein Warten während derEntsorgung: es sorgt dafür, dassfile asynchron entsorgt wird, wenn die Variable außer Geltungsbereich gerät.

await using mitfor 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 können.

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

Zuerst machtawait y das, was Sie erwarten: wirawait das Versprecheny, welches erwartet wird, um sich in ein Objekt aufzulösen, das wir durchlaufen. Lassen Sie uns diese Variante beiseitelegen.

Diefor await...of-Schleife erfordert, dass das Objekty einasynchroner Iterierbar ist. Das bedeutet, dass das Objekt eine[Symbol.asyncIterator]-Methode haben muss, die einenasynchronen Iterator zurückgibt, dessennext()-Methode ein Versprechen zurückgibt, das das Ergebnis darstellt. Dies ist der Fall, wenn der Iterator nicht weiß, was der nächste Wert ist oder sogar, ob es schon fertig ist, bis eine asynchrone Operation abgeschlossen ist.

Andererseits verlangt dieawait using x-Syntax, dass das Objektx, das aus dem Iterator stammt, einasynchron entsorgbar ist. Das bedeutet, dass das Objekt eine[Symbol.asyncDispose]-Methode haben muss, die ein Versprechen zurückgibt, das die Entsorgungsoperation darstellt. Dies ist ein separates Anliegen vom eigentlichen Iterationsvorgang und wird nur aufgerufen, wenn die Variablex außer Geltungsbereich gerät.

Mit anderen Worten, alle folgenden vier Kombinationen sind gültig 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 vony, um ihre Anwendungsfälle zu demonstrieren. Für asynchrone APIs basiert unser Code auf dem Node.jsfs/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 einawait using in einem Geltungsbereich deklariert wird, wird der Bereich immer einawait beim Beenden haben, selbst wenn die Variablenull oderundefined ist. Dies stellt eine stabile Ausführungsreihenfolge und Fehlerbehandlung sicher. Die Beispiele unterKontrollflusseffekte von await enthalten mehr Details dazu.

Im Beispiel unten löst derexample()-Aufruf unten erst eine Takt später auf, aufgrund eines implizitenawait, wenn die Funktion zurückkehrt.

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 synchronenusing stattdessen. Dieses Mal wird derexample()-Aufruf sofort aufgelöst, sodass die beidenthen()-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

Für 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 Ressourcerequired 2 im gleichen Takt wierequired 1 entsorgt. Wenn dieoptional-Ressource kein redundantesawait verursacht hätte, wärerequired 2 früher entsorgt worden, was gleichzeitig mitoptional wäre.

Spezifikationen

Specification
ECMAScript Async Explicit Resource Management
# prod-AwaitUsingDeclaration

Browser-Kompatibilität

Siehe auch

Help improve MDN

Learn how to contribute Diese Seite wurde automatisch aus dem Englischen übersetzt.

[8]ページ先頭

©2009-2026 Movatter.jp