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

using - JavaScript | MDN

Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.

View in English Always switch to English

using

Disponibilit limite

Cette fonctionnalit n'est pas Compatible car elle ne fonctionne pas dans certains des navigateurs les plus utiliss.

Vous voulez une meilleure prise en charge pour cette fonctionnalit ? Dites-nous pourquoi.

La dclaration using dclare des variables locales porte de bloc qui sont libres de faon synchrone. Comme pour const, les variables dclares avec using doivent tre initialises et ne peuvent pas tre raffectes. La valeur de la variable doit tre null, undefined, ou un objet possdant une mthode [Symbol.dispose](). Lorsque la variable sort de la porte, la mthode [Symbol.dispose]() de l'objet est appele pour s'assurer que les ressources sont libres.

Dans cet article

Syntaxe

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

Le nom de la variable dclarer. Chacun doit tre un identifiant JavaScript valide et ne doit pas tre un modle de dcomposition.

valueN

Valeur initiale de la variable. Il peut s'agir de n'importe quelle expression valide, mais sa valeur doit tre null, undefined ou un objet possdant une mthode [Symbol.dispose]().

Description

Cette dclaration peut tre utilise :

Plus prcisment, elle ne peut pas tre utilise :

  • Au niveau suprieur d'un script, car les portes de script sont persistantes.
  • Au niveau suprieur d'une instruction switch.
  • Dans l'initialiseur d'une boucle for...in, car la variable de boucle ne peut tre qu'une chane de caractres ou un symbole.

Un using dclare une ressource jetable lie la dure de vie de la porte de la variable (bloc, fonction, module, etc.). Lorsque la porte se termine, la ressource est libre de faon synchrone. La variable peut valoir null ou undefined, la ressource peut donc tre optionnelle.

Lors de la premire dclaration de la variable, si sa valeur n'est pas nulle/indfinie, une fonction de libration est rcupre depuis l'objet. Si la proprit [Symbol.dispose] ne contient pas une fonction, une TypeError est leve. Cette fonction de libration est enregistre dans la porte.

Quand la variable sort de la porte, la fonction de libration est appele. Si la porte contient plusieurs dclarations using ou await using, toutes les fonctions de libration sont excutes dans l'ordre inverse de leur dclaration, quel que soit le type de dclaration. L'excution de toutes les fonctions de libration est garantie (similaire au bloc finally dans try...catch...finally). Toutes les erreurs leves lors de la libration, y compris l'erreur initiale ayant provoqu la sortie de porte (le cas chant), sont agrges dans un seul SuppressedError, chaque exception antrieure tant place dans la proprit suppressed et la dernire exception dans la proprit error. Ce SuppressedError est lev aprs la fin de la libration.

using lie la gestion des ressources aux portes lexicales, ce qui est la fois pratique et parfois droutant. Il existe plusieurs faons de prserver la valeur de la variable une fois que la variable elle-mme est hors porte, ce qui peut vous amener conserver une rfrence vers une ressource dj libre. Voir les exemples ci-dessous pour des cas o le comportement peut surprendre. Si vous souhaitez grer manuellement la libration des ressources tout en conservant les mmes garanties de gestion d'erreur, vous pouvez utiliser l'objet DisposableStack.

Exemples

Dans les exemples suivants, nous supposons une classe simple Resource qui possde une mthode getValue et une mthode [Symbol.dispose]() :

js
class Resource {
  value = Math.random();
  #isDisposed = false;

  getValue() {
    if (this.#isDisposed) {
      throw new Error("La ressource est libre");
    }
    return this.value;
  }

  [Symbol.dispose]() {
    this.#isDisposed = true;
    console.log("Ressource libre");
  }
}

using dans un bloc

La ressource dclare avec using est libre lors de la sortie du bloc.

js
{
  using resource = new Resource();
  console.log(resource.getValue());
  // Ressource libre ici
}

using dans une fonction

Vous pouvez utiliser using dans le corps d'une fonction. Dans ce cas, la ressource est libre lorsque la fonction termine son excution, immdiatement avant que la fonction ne retourne.

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

Ici, resource[Symbol.dispose]() sera appel aprs getValue(), avant l'excution de la dclaration return.

La ressource peut survivre la dclaration si elle est capture par une fermeture :

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

Dans ce cas, si vous appelez example()(), vous excuterez toujours getValue sur une ressource dj libre, car la ressource a t libre lorsque example retourne. Si vous voulez librer la ressource immdiatement aprs que la fonction de rappel ait t appele une fois, considrez ce modle :

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

Ici, nous aliasons une ressource dclare avec const une ressource dclare avec using, de sorte que la ressource n'est libre qu'aprs la fonction de rappel ; notez que si celle-ci n'est jamais appele, la ressource ne sera jamais nettoye.

using dans un module

Vous pouvez utiliser using au niveau suprieur d'un module. Dans ce cas, la ressource est libre lorsque le module a fini de s'excuter.

js
using resource = new Resource();
export const value = resource.getValue();
// Ressource libre ici

export using est une syntaxe invalide, mais vous pouvez export une variable dclare ailleurs l'aide de using :

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

Cela reste dconseill, car l'importateur recevra toujours une ressource dj libre. Comme pour le problme de la closure, cela prolonge la dure de vie de la valeur au-del de la porte de la variable.

using avec for...of

Vous pouvez utiliser using dans l'initialiseur d'une boucle for...of. Dans ce cas, la ressource est libre chaque itration de la boucle.

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

Dclarer plusieurs using

Les deux formes suivantes sont quivalentes pour dclarer plusieurs ressources jetables :

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

// OU

using resource1 = new Resource();
using resource2 = new Resource();

Dans les deux cas, lorsque la porte se termine, resource2 est libre avant resource1. En effet, resource2 peut dpendre de resource1, il faut donc la librer en premier pour s'assurer que resource1 reste disponible lors de la libration de resource2.

using optionnel

using permet la variable d'avoir la valeur null ou undefined, la ressource peut donc tre optionnelle. Par exemple, si vous vrifiez la disponibilit d'une ressource :

js
function acquireResource() {
  // Imaginez ici une condition pertinente du monde rel,
  // par exemple s'il y a suffisamment d'espace pour allouer cette ressource
  if (Math.random() < 0.5) {
    return null;
  }
  return new Resource();
}

Vous n'avez pas faire ceci :

js
const maybeResource = acquireResource();

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

Et pouvez plutt faire ceci :

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

Dclaration using sans utiliser la variable

Vous pouvez obtenir la libration automatique des ressources avec using, sans mme utiliser la variable. Cela est trs utile pour tablir un contexte dans un bloc, par exemple pour crer un verrou :

js
{
  using _ = new Lock();
  // Effectuer des oprations concurrentes ici
  // Verrou libr ici
}

Notez que _ est un identifiant normal, mais c'est une convention de l'utiliser comme variable  jetable . Pour crer plusieurs variables inutilises, vous devez utiliser des noms distincts, par exemple en prfixant le nom par _.

Initialisation et zones mortes temporelles

Les variables using sont soumises la mme restriction de zone morte temporelle que les variables let et const. Cela signifie que vous ne pouvez pas accder la variable avant son initialisation la dure de vie valide de la ressource s'tend strictement de son initialisation la fin de sa porte. Cela permet une gestion des ressources de type RAII.

js
let useResource;
{
  useResource = () => resource.getValue();
  useResource(); // Erreur : Impossible d'accder  'resource' avant son initialisation
  using resource = new Resource();
  useResource(); // Valide
}
useResource(); // Erreur : Ressource libre

Gestion des erreurs

La dclaration using est particulirement utile pour grer la libration des ressources en prsence d'erreurs. Si vous n'tes pas prudent, certaines ressources peuvent fuir parce qu'une erreur empche l'excution du code suivant.

js
function handleResource(resource) {
  if (resource.getValue() > 0.5) {
    throw new Error("Valeur de ressource trop leve");
  }
}

try {
  using resource = new Resource();
  handleResource(resource);
} catch (e) {
  console.error(e);
}

Ceci attrapera correctement l'erreur leve par handleResource et l'enregistrera, que handleResource lve une erreur ou non, la ressource est libre avant la sortie du bloc try.

Ici, si vous n'utilisez pas using, vous pourriez faire quelque chose comme :

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

Mais si handleResource() lve une erreur, le contrle n'atteint jamais resource[Symbol.dispose](), et la ressource fuit. De plus, si vous avez deux ressources, les erreurs leves lors des premires librations peuvent empcher l'excution des librations suivantes, entranant d'autres fuites.

Considrez un cas plus compliqu o la fonction de libration elle-mme lance une erreur :

js
class CantDisposeMe {
  #name;
  constructor(name) {
    this.#name = name;
  }
  [Symbol.dispose]() {
    throw new Error(`Impossible de librer ${this.#name}`);
  }
}

let error;

try {
  using resource1 = new CantDisposeMe("resource1");
  using resource2 = new CantDisposeMe("resource2");
  throw new Error("Erreur dans le bloc principal");
} catch (e) {
  error = e;
}

Vous pouvez inspecter l'erreur leve dans la console de votre navigateur. Elle a la structure suivante :

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

Comme vous pouvez le voir, error contient toutes les erreurs qui ont t leves lors de la libration, sous la forme d'un SuppressedError. Chaque erreur supplmentaire est ajoute comme proprit error, et l'erreur originale est ajoute comme proprit suppressed.

Spcifications

Spcification
ECMAScript Async Explicit Resource Management
# prod-UsingDeclaration

Compatibilit des navigateurs

Voir aussi


Web Proxy Viewer  |  New URL  |  Original Page