Movatterモバイル変換


[0]ホーム

URL:


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

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

View in EnglishAlways switch to English

using

Limited availability

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

Dieusing-Deklaration erklärt block-skopierte lokale Variablen, diesynchron freigegeben werden. Wie beiconst müssen Variablen, die mitusing deklariert werden, initialisiert werden und können nicht neu zugewiesen werden. Der Wert der Variable muss entwedernull,undefined oder ein Objekt mit einer[Symbol.dispose]()-Methode sein. Wenn die Variable außer Reichweite gerät, wird die[Symbol.dispose]()-Methode des Objekts aufgerufen, um sicherzustellen, dass Ressourcen freigegeben werden.

Syntax

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

Der Name der zu deklarierenden Variable. Jede muss ein gültiger JavaScript-Bezeichner sein undkeinDestrukturierungs-Bindungsmuster.

valueN

Anfangswert der Variablen. Es kann jeder gültige Ausdruck sein, aber sein Wert muss entwedernull,undefined oder ein Objekt mit einer[Symbol.dispose]()-Methode sein.

Beschreibung

Diese Deklaration kann verwendet werden:

Es kann nicht verwendet werden:

  • Auf der obersten Ebene eines Skripts, da Skript-Skopen persistent sind.
  • Auf der obersten Ebene einerswitch-Anweisung.
  • In der Initialisierung einerfor...in-Schleife. Da die Schleifenvariable nur eine Zeichenkette oder ein Symbol sein kann, ergibt dies keinen Sinn.

Einusing erklärt eine freigebbare Ressource, die mit der Lebensdauer des Skopenumfangs der Variable (Block, Funktion, Modul usw.) verbunden ist. Wenn das Skopus endet, wird die Ressource synchron freigegeben. Die Variable darf den Wertnull oderundefined haben, sodass die Ressource optional vorhanden sein kann.

Wenn die Variable zuerst deklariert wird und ihr Wert nicht null ist, wird einDisposer vom Objekt abgerufen. Wenn die[Symbol.dispose]-Eigenschaft keine Funktion enthält, wird einTypeError ausgelöst. Dieser Disposer wird im Umfang gespeichert.

Wenn die Variable außer Reichweite gerät, wird der Disposer aufgerufen. Wenn der Skopus mehrereusing oderawait using-Deklarationen enthält, werden alle Disposer in umgekehrter Reihenfolge der Deklaration ausgeführt, unabhängig von der Art der Deklaration. Alle Disposer werden garantiert ausgeführt (ähnlich wie derfinally-Block intry...catch...finally). Alle während der Freigabe auftretenden Fehler, einschließlich des anfänglichen Fehlers, der das Skopus-Ende verursacht hat (falls zutreffend), werden alle in einemSuppressedError aggregiert, wobei jede frühere Ausnahme alssuppressed-Eigenschaft und die spätere Ausnahme alserror-Eigenschaft dient. DieserSuppressedError wird geworfen, nachdem die Freigabe abgeschlossen ist.

using verknüpft das Ressourcenmanagement mit lexikalischen Skopen, was sowohl praktisch als auch manchmal verwirrend ist. Es gibt viele Möglichkeiten, den Wert der Variable zu bewahren, wenn die Variable selbst außer Reichweite ist, sodass Sie möglicherweise einen Verweis auf eine bereits freigegebene Ressource halten. Unten finden Sie Beispiele, bei denen es möglicherweise nicht wie erwartet funktioniert. Wenn Sie die Freigabe von Ressourcen selbst verwalten möchten, während Sie die gleichen Garantien für Fehlerbehandlung einhalten, können Sie stattdessenDisposableStack verwenden.

Beispiele

In den folgenden Beispielen nehmen wir eine einfacheResource-Klasse an, die einegetValue-Methode und eine[Symbol.dispose]()-Methode hat:

js
class Resource {  value = Math.random();  #isDisposed = false;  getValue() {    if (this.#isDisposed) {      throw new Error("Resource is disposed");    }    return this.value;  }  [Symbol.dispose]() {    this.#isDisposed = true;    console.log("Resource disposed");  }}

using in einem Block

Die mitusing deklarierte Ressource wird beim Verlassen des Blocks freigegeben.

js
{  using resource = new Resource();  console.log(resource.getValue());  // resource disposed here}

using in einer Funktion

Sie könnenusing in einem Funktionskörper verwenden. In diesem Fall wird die Ressource freigegeben, wenn die Funktion ihre Ausführung beendet, unmittelbar bevor die Funktion zurückkehrt.

js
function example() {  using resource = new Resource();  return resource.getValue();}

Hier wirdresource[Symbol.dispose]() nachgetValue(), aber bevor diereturn-Anweisung ausgeführt wird, aufgerufen.

Die Ressource kann die Deklaration überleben, falls sie von einemClosure eingefangen wird:

js
function example() {  using resource = new Resource();  return () => resource.getValue();}

In diesem Fall, wenn Sieexample()() aufrufen, wird stetsgetValue auf eine Ressource ausgeführt, die bereits freigegeben wurde, da die Ressource freigegeben wurde, alsexample zurückkehrte. Falls Sie die Ressource sofort nach einmaligem Aufrufen des Rückrufs freigeben möchten, erwägen Sie dieses Muster:

js
function example() {  const resource = new Resource();  return () => {    using resource2 = resource;    return resource2.getValue();  };}

Hier, wiraliasen eine mitconst deklarierte Ressource zu einer mitusing deklarierten Ressource, sodass die Ressource erst nach dem Aufruf des Rückrufs freigegeben wird; beachten Sie, dass die Ressource niemals bereinigt wird, wenn sie nie aufgerufen wird.

using in einem Modul

Sie könnenusing auf der obersten Ebene eines Moduls verwenden. In diesem Fall wird die Ressource freigegeben, wenn das Modul die Ausführung beendet.

js
using resource = new Resource();export const value = resource.getValue();// resource disposed here

export using ist ungültige Syntax, aber Sie können eine anderswo mitusing deklarierte Variableexportieren:

js
using resource = new Resource();export { resource };

Dies wird dennoch abgeraten, da der Importeur immer eine freigegebene Ressource erhält. Ähnlich wie beim Closure-Problem führt dies dazu, dass der Wert der Ressource länger besteht als die Variable.

using mitfor...of

Sie könnenusing in der Initialisierung einerfor...of-Schleife verwenden. In diesem Fall wird die Ressource in jeder Schleifeniteration freigegeben.

js
const resources = [new Resource(), new Resource(), new Resource()];for (using resource of resources) {  console.log(resource.getValue());  // resource disposed here}

Mehrereusing

Die folgenden sind zwei gleichwertige Möglichkeiten, mehrere freigebbare Ressourcen zu deklarieren:

js
using resource1 = new Resource(),  resource2 = new Resource();// ORusing resource1 = new Resource();using resource2 = new Resource();

In beiden Fällen wird, wenn das Skop endet,resource2 vorresource1 freigegeben. Dies liegt daran, dassresource2 möglicherweise vonresource1 abhängt, daher wird es zuerst freigegeben, um sicherzustellen, dassresource1 noch verfügbar ist, wennresource2 freigegeben wird.

Optionalusing

using erlaubt der Variable, einen Wert vonnull oderundefined zu haben, sodass die Ressource optional vorhanden sein kann. Dies bedeutet, dass Sie beispielsweise bei der Überprüfung der Verfügbarkeit einer Ressource irgendeiner Art:

js
function acquireResource() {  // Imagine some real-world relevant condition here,  // such as whether there's space to allocate for this resource  if (Math.random() < 0.5) {    return null;  }  return new Resource();}

nicht tun müssen:

js
const maybeResource = acquireResource();if (maybeResource) {  using resource = maybeResource;  console.log(resource.getValue());} else {  console.log(undefined);}

Stattdessen können Sie dies tun:

js
using resource = acquireResource();console.log(resource?.getValue());

using-Deklaration ohne Verwendung der Variable

Sie können automatisches Freigeben von Ressourcen mitusing erreichen, ohne die Variable zu verwenden. Dies ist sehr nützlich, um einen Kontext innerhalb eines Blocks einzurichten, wie das Erstellen einer Sperre:

js
{  using _ = new Lock();  // Perform concurrent operations here  // Lock disposed (released) here}

Beachten Sie, dass_ ein normaler Bezeichner ist, jedoch konventionell als "Wegwerf"-Variable verwendet wird. Um mehrere ungenutzte Variablen zu erstellen, müssen Sie unterschiedliche Namen verwenden, z.B. indem Sie einen Variablennamen mit_ voranstellen.

Initialisierung und temporale tote Zonen

using-Variablen unterliegen den gleichentemporal dead zone-Einschränkungen wielet- undconst-Variablen. Das bedeutet, dass Sie nicht auf die Variable zugreifen können, bevor sie initialisiert ist—die gültige Lebensdauer der Ressource reicht strikt von der Initialisierung bis zum Ende ihres Skopos. Dies ermöglichtRAII-ähnliches Ressourcenmanagement.

js
let useResource;{  useResource = () => resource.getValue();  useResource(); // Error: Cannot access 'resource' before initialization  using resource = new Resource();  useResource(); // Valid}useResource(); // Error: Resource is disposed

Fehlerbehandlung

Dieusing-Deklaration ist am nützlichsten für das Verwalten der Ressourcenfreigabe bei Vorhandensein von Fehlern. Wenn Sie nicht vorsichtig sind, können einige Ressourcen auslaufen, weil der Fehler das nachfolgende Ausführen von Code verhindert.

js
function handleResource(resource) {  if (resource.getValue() > 0.5) {    throw new Error("Resource value too high");  }}try {  using resource = new Resource();  handleResource(resource);} catch (e) {  console.error(e);}

Dies wird den vonhandleResource ausgelösten Fehler erfolgreich abfangen und protokollieren, und unabhängig davon, obhandleResource einen Fehler auslöst oder nicht, wird die Ressource vor dem Verlassen destry-Blocks freigegeben.

Hier, wenn Sieusing nicht verwenden, könnten Sie so etwas tun:

js
try {  const resource = new Resource();  handleResource(resource);  resource[Symbol.dispose]();} catch (e) {  console.error(e);}

Wenn jedochhandleResource() einen Fehler auslöst, erreicht die Kontrolle niemalsresource[Symbol.dispose](), und die Ressource wird nicht freigegeben. Darüber hinaus können Fehler, die beim Freigeben früherer Ressourcen auftreten, verhindern, dass später freigegebene Ressourcen ausgeführt werden, was zu weiteren Lecks führt.

Betrachten Sie einen komplizierteren Fall, bei dem der Disposer selbst einen Fehler auslöst:

js
class CantDisposeMe {  #name;  constructor(name) {    this.#name = name;  }  [Symbol.dispose]() {    throw new Error(`Can't dispose ${this.#name}`);  }}let error;try {  using resource1 = new CantDisposeMe("resource1");  using resource2 = new CantDisposeMe("resource2");  throw new Error("Error in main block");} catch (e) {  error = e;}

Sie können den in der Konsole Ihres Browsers geworfenen Fehler untersuchen. Er hat folgende Struktur:

SuppressedError: An error was suppressed during disposal  suppressed: SuppressedError: An error was suppressed during disposal    suppressed: Error: Can't dispose resource1    error: Error: Error in main block  error: Error: Can't dispose resource2

Wie Sie sehen, enthälterror alle während der Freigabe geworfenen Fehler alsSuppressedError. Jeder zusätzliche Fehler wird als dieerror-Eigenschaft hinzugefügt, und der ursprüngliche Fehler wird als diesuppressed-Eigenschaft hinzugefügt.

Spezifikationen

Specification
ECMAScript Async Explicit Resource Management
# prod-UsingDeclaration

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