[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/fr/docs/Web/API/HTML_DOM_API/Microtask_guide [Back]  [Original]

Utiliser les microtches en JavaScript avec queueMicrotask() - Les API Web | 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

Utiliser les microtches en JavaScript avec queueMicrotask()

Une microtche est une courte fonction qui s'excute aprs que la fonction ou le programme qui l'a cre se termine et uniquement si la pile d'excution JavaScript est vide, mais avant de rendre le contrle la boucle d'vnements utilise par l'agent utilisateur pour grer l'environnement d'excution du script.

Cttte boucle d'vnement peut tre soit la boucle d'vnements principale du navigateur, soit la boucle d'vnements d'un web worker. Cela permet la fonction donne de s'excuter sans risquer d'interfrer avec l'excution d'un autre script, tout en garantissant que la microtche s'excute avant que l'agent utilisateur n'ait l'occasion de ragir aux actions effectues par la microtche.

Les promesses JavaScript et l'API Mutation Observer utilisent toutes deux la file d'attente des microtches pour excuter leurs rappels, mais il existe d'autres moments o la possibilit de diffrer le travail jusqu' la fin du passage actuel de la boucle d'vnements est utile. Afin de permettre aux microtches d'tre utilises par des bibliothques tierces, des frameworks et des prothses d'mulations, la mthode queueMicrotask() est expose sur les interfaces Window et WorkerGlobalScope.

Dans cet article

Tches et microtches

Pour discuter correctement des microtches, il est d'abord utile de savoir ce qu'est une tche JavaScript et comment les microtches diffrent des tches. Il s'agit d'une explication rapide et simplifie, mais si vous souhaitez plus de dtails, vous pouvez lire les informations dans l'article Aller plus loin : Les microtches et l'environnement d'excution JavaScript.

Tches

Une tche est tout ce qui est programm pour tre excut par les mcanismes standard, tels que le dmarrage initial d'un programme, la distribution asynchrone d'un vnement ou le dclenchement d'un intervalle ou d'un dlai. Toutes ces actions sont programmes dans la file d'attente des tches.

Par exemple, les tches sont ajoutes la file d'attente des tches lorsque :

  • Un nouveau programme ou sous-programme JavaScript est excut (par exemple depuis une console, ou en excutant le code dans un lment HTML <script>) directement.
  • L'utilisateurice clique sur un lment. Une tche est alors cre et excute tous les rappels d'vnements.
  • Un dlai ou un intervalle cr avec setTimeout() ou setInterval() est atteint, ce qui entrane l'ajout du rappel correspondant la file d'attente des tches.

La boucle d'vnements qui excute votre code gre ces tches les unes aprs les autres, dans l'ordre dans lequel elles ont t mises en file d'attente. La tche excutable la plus ancienne dans la file d'attente des tches sera excute lors d'une seule itration de la boucle d'vnements. Aprs cela, les microtches seront excutes jusqu' ce que la file d'attente des microtches soit vide, puis le navigateur peut choisir de mettre jour le rendu. Ensuite, le navigateur passe l'itration suivante de la boucle d'vnements.

Microtches

Au premier abord, la diffrence entre les microtches et les tches semble mineure. Et elles sont similaires ; toutes deux sont constitues de code JavaScript qui est plac dans une file d'attente et excut au moment appropri. Cependant, alors que la boucle d'vnements excute uniquement les tches prsentes dans la file d'attente au dbut de l'itration, une par une, elle gre la file d'attente des microtches de manire trs diffrente.

Il y a deux diffrences cls :

  1. Chaque fois qu'une tche se termine, la boucle d'vnements vrifie si la tche rend le contrle un autre code JavaScript. Si ce n'est pas le cas, elle excute toutes les microtches prsentes dans la file d'attente des microtches. La file d'attente des microtches est donc traite plusieurs fois par itration de la boucle d'vnements, y compris aprs le traitement des vnements et d'autres rappels.
  2. Si une microtche ajoute d'autres microtches la file d'attente en appelant queueMicrotask(), ces microtches nouvellement ajoutes s'excutent avant que la tche suivante ne soit excute. C'est parce que la boucle d'vnements continuera appeler les microtches jusqu' ce qu'il n'en reste plus dans la file d'attente, mme si d'autres continuent tre ajoutes.

Attention : Comme les microtches peuvent elles-mmes mettre en file d'attente d'autres microtches, et que la boucle d'vnements continue traiter les microtches jusqu' ce que la file soit vide, il y a un rel risque que la boucle d'vnements traite les microtches indfiniment. Soyez prudente avec la manire dont vous ajoutez des microtches de manire rcursive.

Utiliser des microtches

Avant d'aller plus loin, il est important de noter nouveau que la plupart des dveloppeureuses n'utiliseront pas beaucoup les microtches, voire pas du tout. Il s'agit d'une fonctionnalit trs spcialise du dveloppement JavaScript moderne bas sur le navigateur, permettant de programmer du code pour qu'il passe devant d'autres choses dans la longue liste des choses en attente sur l'ordinateur de l'utilisateurice. Abuser de cette capacit entranera des problmes de performance.

Mettre en file d'attente des microtches

Ainsi, vous ne devriez gnralement utiliser les microtches que lorsqu'il n'y a pas d'autre solution, ou lors de la cration de frameworks ou de bibliothques qui doivent utiliser des microtches pour crer la fonctionnalit qu'ils implmentent. Bien qu'il y ait eu des astuces disponibles qui permettaient de mettre en file d'attente des microtches dans le pass (comme en crant une promesse qui se rsout immdiatement), l'ajout de la mthode queueMicrotask() offre un moyen standard d'introduire une microtche de manire sre et sans astuces.

En introduisant queueMicrotask(), les particularits qui surviennent lorsqu'on utilise des promesses pour crer des microtches peuvent tre vites. Par exemple, lorsqu'on utilise des promesses pour crer des microtches, les exceptions lances par le rappel sont signales comme des promesses rejetes plutt que comme des exceptions standard. De plus, la cration et la destruction de promesses entranent un surcot supplmentaire en termes de temps et de mmoire, ce qu'une fonction qui met correctement en file d'attente des microtches vite.

Passez l'objet Function JavaScript appeler pendant que le contexte gre les microtches dans la mthode queueMicrotask(), qui est expose sur le contexte global tel que dfini par l'interface Window ou Worker, selon le contexte d'excution actuel.

js
queueMicrotask(() => {
  /* code  excuter dans la microtche ici */
});

La fonction de microtche elle-mme ne prend aucun paramtre et ne retourne aucune valeur.

Quand utiliser les microtches ?

Dans cette section, nous allons examiner les scnarios dans lesquels les microtches sont particulirement utiles. En gnral, il s'agit de capturer ou de vrifier des rsultats, ou d'effectuer un nettoyage, aprs que le corps principal d'un contexte d'excution JavaScript se termine, mais avant que les gestionnaires d'vnements, les minuteries et intervalles, ou d'autres rappels ne soient traits.

Quand est-ce utile ?

La principale raison d'utiliser des microtches est de garantir un ordre cohrent des tches, mme lorsque les rsultats ou les donnes sont disponibles de manire synchrone, tout en rduisant simultanment le risque de retards perceptibles par l'utilisateurice dans les oprations.

Garantir l'ordre lors de l'utilisation conditionnelle des promesses

Une situation dans laquelle les microtches peuvent tre utilises pour garantir que l'ordre d'excution est toujours cohrent est lorsque des promesses sont utilises dans une clause d'une instruction if...else (ou autre instruction conditionnelle), mais pas dans l'autre clause. Considrons un code comme celui-ci :

js
customElement.prototype.getData = function (url) {
  if (this.cache[url]) {
    this.data = this.cache[url];
    this.dispatchEvent(new Event("load"));
  } else {
    fetch(url)
      .then((result) => result.arrayBuffer())
      .then((data) => {
        this.cache[url] = data;
        this.data = data;
        this.dispatchEvent(new Event("load"));
      });
  }
};

Le problme introduit ici est qu'en utilisant une tche dans une branche de l'instruction if...else (dans le cas o l'image est disponible dans le cache) mais en ayant des promesses impliques dans la clause else, nous avons une situation dans laquelle l'ordre des oprations peut varier ; par exemple, comme on le voit ci-dessous.

js
element.addEventListener("load", () =>
  console.log("Chargement des donnes termin"),
);
console.log("Rcupration des donnes");
element.getData();
console.log("Donnes rcupres");

Excuter ce code deux fois de suite donne les rsultats suivants.

Lorsque les donnes ne sont pas en cache :

Rcupration des donnes
Donnes rcupres
Chargement des donnes termin

Lorsque les donnes sont en cache :

Rcupration des donnes
Chargement des donnes termin
Donnes rcupres

Encore pire, parfois la proprit data de l'lment sera dfinie, mais d'autres fois elle ne sera pas complte avant que ce code ne termine son excution.

Nous pouvons garantir un ordre cohrent de ces oprations en utilisant une microtche dans la clause if pour quilibrer les deux clauses :

js
customElement.prototype.getData = function (url) {
  if (this.cache[url]) {
    queueMicrotask(() => {
      this.data = this.cache[url];
      this.dispatchEvent(new Event("load"));
    });
  } else {
    fetch(url)
      .then((result) => result.arrayBuffer())
      .then((data) => {
        this.cache[url] = data;
        this.data = data;
        this.dispatchEvent(new Event("load"));
      });
  }
};

Cela quilibre les clauses en faisant en sorte que les deux situations grent la dfinition de data et le dclenchement de l'vnement load dans une microtche (en utilisant queueMicrotask() dans la clause if et en utilisant les promesses utilises par fetch() dans la clause else).

Regroupement des oprations

Vous pouvez galement utiliser des microtches pour collecter plusieurs requtes provenant de diffrentes sources dans un seul lot, vitant ainsi le surcot possible li plusieurs appels pour grer le mme type de travail.

L'extrait ci-dessous cre une fonction qui regroupe plusieurs messages dans un tableau, en utilisant une microtche pour les envoyer en tant qu'objet unique lorsque le contexte se termine.

js
const messageQueue = [];

let sendMessage = (message) => {
  messageQueue.push(message);

  if (messageQueue.length === 1) {
    queueMicrotask(() => {
      const json = JSON.stringify(messageQueue);
      messageQueue.length = 0;
      fetch("url-de-reception", json);
    });
  }
};

Lorsque sendMessage() est appel, le message dfini est d'abord ajout au tableau de la file d'attente des messages. Ensuite, les choses deviennent intressantes.

Si le message que nous venons d'ajouter au tableau est le premier, nous mettons en file d'attente une microtche qui enverra un lot. La microtche s'excutera, comme toujours, lorsque le chemin d'excution JavaScript atteindra le niveau suprieur, juste avant d'excuter les rappels. Cela signifie que tout autre appel sendMessage() effectu entre-temps ajoutera ses messages la file d'attente des messages, mais en raison de la vrification de la longueur du tableau avant d'ajouter une microtche, aucune nouvelle microtche n'est mise en file d'attente.

Lorsque la microtche s'excute, elle dispose alors d'un tableau de nombreux messages potentiellement en attente. Elle commence par les encoder en JSON en utilisant la mthode JSON.stringify(). Aprs cela, le contenu du tableau n'est plus ncessaire, nous vidons donc le tableau messageQueue. Enfin, nous utilisons la mthode fetch() pour envoyer la chane de caractres JSON au serveur.

Cela permet chaque appel sendMessage() effectu pendant la mme itration de la boucle d'vnements d'ajouter ses messages la mme opration fetch(), sans que d'autres tches telles que des minuteries ou autres ne retardent potentiellement la transmission.

Le serveur recevra la chane de caractres JSON, puis la dcodera probablement et traitera les messages qu'il trouve dans le tableau rsultant.

Exemples

Exemple simple de microtche

Dans cet exemple simple, nous voyons que la mise en file d'attente d'une microtche fait en sorte que le rappel de la microtche s'excute aprs que le corps de ce script de niveau suprieur a termin son excution.

JavaScript

Dans le code suivant, nous voyons un appel queueMicrotask() utilis pour planifier l'excution d'une microtche. Cet appel est encadr par des appels journaliser(), une fonction personnalise qui affiche du texte l'cran.

js
journaliser("Avant la mise en file d'attente de la microtche");
queueMicrotask(() => {
  journaliser("La microtche s'est excute.");
});
journaliser("Aprs la mise en file d'attente de la microtche");

Rsultat

Exemple de dlais d'attente et de microtche

Dans cet exemple, un dlai d'attente est programm pour s'excuter aprs zro millisecondes (ou  aussi vite que possible ). Cela dmontre la diffrence entre ce que signifie  aussi vite que possible  lors de la planification d'une nouvelle tche (par exemple en utilisant setTimeout()) par rapport l'utilisation d'une microtche.

JavaScript

Dans le code suivant, nous voyons un appel queueMicrotask() utilis pour planifier l'excution d'une microtche. Cet appel est encadr par des appels journaliser(), une fonction personnalise qui affiche du texte l'cran.

Le code ci-dessous programme un dlai d'attente pour s'excuter aprs zro millisecondes, puis met en file d'attente une microtche. Cela est encadr par des appels journaliser() pour afficher des messages supplmentaires.

js
const callback = () =>
  journaliser("Le rappel du dlai d'attente rgulier s'est excut");

const urgentCallback = () =>
  journaliser("*** Oh non ! Un rappel urgent s'est excut !");

journaliser("Le programme principal a commenc");
setTimeout(callback, 0);
queueMicrotask(urgentCallback);
journaliser("Le programme principal se termine");

Rsultat

Notez que la sortie enregistre partir du corps du programme principal apparat en premier, suivie de la sortie de la microtche, puis du rappel du dlai d'attente. Cela s'explique par le fait que lorsque la tche qui gre l'excution du programme principal se termine, la file d'attente des microtches est traite avant la file d'attente des tches sur laquelle se trouve le rappel du dlai d'attente. Pour aider garder cela en tte, rappelez-vous que les tches et les microtches sont conserves dans des files d'attente spares, et que les microtches s'excutent en premier.

Microtche partir d'une fonction

Cet exemple s'tend lgrement sur le prcdent en ajoutant une fonction qui effectue un certain travail. Cette fonction utilise queueMicrotask() pour planifier une microtche. L'lment important retenir est que la microtche n'est pas traite lorsque la fonction se termine, mais lorsque le programme principal se termine.

JavaScript

Le code principal du programme suit. La fonction faireTravail() appelle ici queueMicrotask(), mais la microtche ne s'excute toujours pas avant la fin de l'ensemble du programme, car c'est ce moment-l que la tche se termine et qu'il n'y a rien d'autre sur la pile d'excution.

js
const fonctionRappel = () =>
  journaliser("Un dlais d'attente d'une fonction de rappel a t excut");

const fonctionRappelUrgent = () =>
  journaliser("*** Oh non ! Une fonction de rappel urgente a t excute !");

const faireTravail = () => {
  let resultat = 1;

  queueMicrotask(fonctionRappelUrgent);

  for (let i = 2; i <= 10; i++) {
    resultat *= i;
  }
  return resultat;
};

journaliser("Le programme principal a commenc");
setTimeout(fonctionRappel, 0);
journaliser(`10 ! gal ${faireTravail()}`);
journaliser("Le programme principal se termine");

Rsultat

Voir aussi


Web Proxy Viewer  |  New URL  |  Original Page