Web Worker en JavaScript : un calcul lourd sans figer la page

Un Web Worker exécute du JavaScript dans un fil séparé. La page reste réactive, mais le worker ne touche pas au DOM et ne parle que par messages.
3 min de lecture
Believemy logo

Un tri sur cent mille lignes, une image redimensionnée, un fichier analysé au chargement : pendant ces quelques secondes, la page ne répond plus. Les clics s'accumulent, les animations se figent, le curseur tourne.

La cause tient à une règle simple : JavaScript n'exécute qu'une chose à la fois dans une page. Une seule interface permet d'en sortir.


Définition

Un Web Worker est un script exécuté par le navigateur dans un fil d'exécution séparé, en parallèle de la page. Il ne partage aucune variable avec elle et communique uniquement par messages.

JAVASCRIPT
// page.js
const travailleur = new Worker("calcul.js");

travailleur.postMessage({ lignes: 5000000 });

travailleur.onmessage = (evenement) => {
  console.log(evenement.data.total);
  travailleur.terminate();
};
JAVASCRIPT
// calcul.js
self.onmessage = (evenement) => {
  let total = 0;
  for (let i = 0; i < evenement.data.lignes; i++) {
    total += i;
  }
  self.postMessage({ total });
};

Pendant la boucle, la page reste parfaitement réactive. Le mot-clé self désigne le worker lui-même, à la place de la fenêtre : this n'y pointe pas sur le même objet que dans une page.


Ce dont le worker ne dispose pas

L'isolement a un prix. Un worker vit sans page, ce qui lui retire une bonne partie des outils habituels.

  • Aucun accès au DOM : ni document, ni querySelector(), ni la moindre modification d'affichage.
  • Pas de stockage synchrone : localStorage n'existe pas dans ce contexte, contrairement à IndexedDB.
  • Pas de variables partagées : le worker ne voit rien de ce que la page a défini.

En revanche, fetch(), JSON, les minuteries et les expressions RegExp y fonctionnent normalement. Le calcul part dans le worker, l'affichage du résultat revient à la page.


Ce qui traverse un message

Les données envoyées sont copiées selon l'algorithme de clonage structuré, pas partagées. Trois conséquences valent d'être connues.

  • Une fonction ne passe pas : l'envoi échoue avec une erreur de clonage.
  • Une instance de class perd son prototype : elle arrive sous forme d'objet simple, sans ses méthodes.
  • Un gros tampon peut être transféré plutôt que copié, en le passant en second argument de postMessage.
Bon à savoir

Un worker est un fichier chargé par le navigateur, pas un module importé. Avec un outil de compilation, l'écriture attendue est new Worker(new URL("./calcul.js", import.meta.url), { type: "module" }), faute de quoi le fichier n'est pas repris dans la construction.


Questions fréquentes

Question

async ne suffit-il pas à ne pas bloquer la page ?

Non, et la confusion est fréquente. Une fonction async organise l'attente d'un résultat, elle n'ajoute aucun fil d'exécution. Une boucle lourde placée dans une telle fonction bloque la page exactement comme ailleurs, parce qu'elle occupe le même fil, celui que décrit l'Event loop (boucle d'événements).


Question

Combien de workers peut-on lancer ?

Techniquement beaucoup, utilement peu. Chacun consomme sa propre mémoire et son propre temps de démarrage, et au-delà du nombre de cœurs de la machine, ils se disputent les mêmes ressources. La valeur navigator.hardwareConcurrency donne un ordre de grandeur pour dimensionner un groupe de workers réutilisés.


Question

Comment savoir qu'un worker a échoué ?

Un worker n'interrompt jamais la page : une erreur interne y reste enfermée. L'événement error sur l'objet côté page en transmet le message, et messageerror signale une donnée que le clonage n'a pas su transporter. Sans ces deux écouteurs, un worker en panne se contente de ne jamais répondre.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.