Introduction aux web workers

By Thomas Gonzalez|Posted 07 Juin, 2022

Introduction aux web workers

La nature asynchrone de JavaScript le rend parfait pour les navigateurs Web car il permet aux scripts de s’exécuter en concurrence. Cela signifie que nous pouvons créer des animations et d’autres éléments interactifs sur une page Web sans avoir à attendre que les autres scripts aient fini de s’exécuter. Cependant, comme nous allons voir, cela peut s’avérer problématique dans certains cas.

Les limites du code asynchrone 

Un exemple simple :

Imaginons une page web qui demande à un utilisateur de saisir un nombre, dans le but de lui retourner la liste de nombres premiers qui précèdent ce nombre. La fonction appelée serait la suivante :

Tout se passe à peu près bien si le nombre est petit. Mais que se passe-t-il si l’utilisateur saisit un grand nombre ? La page devient inutilisable jusqu’à ce que le calcul soit fini.

La popularité de JavaScript en a fait un langage très utilisé, dans différents environnements (mobile, web, serveur…). 

Mais les contraintes inhérentes à sa conception n’ont pas disparu pour autant. Les développeurs JavaScript sont confrontés à ce genre de problématiques dès qu’ils s’écartent un peu trop des cas standards d’utilisations de JavaScript, notamment avec :

  • Des calculs plus lourds.
  • Tout code qui est susceptible de bloquer la boucle événementielle.
  • Des opérations synchrones, notamment en IO.
 

JavaScript étant lui-même dépourvu des éléments permettant la gestion de thread, une solution “externe” existe : les “workers”.

Présentation des workers 

Les difficultés mentionnées plus haut sont surmontables en utilisant des “workers”. 

Ce sont des outils qui vont permettre d’exécuter des tâches en arrière-plan, comme on le ferait avec un thread.

 On parle alors de “workers thread” avec Node.js et de “web workers” avec les navigateurs.

Remarque : les workers sont rattachés à des threads (au sens du système d’exploitation).

Les workers sont une solution élégante car :

  • Supportés par les environnements (via leurs API respectives), ils ne remettent pas en cause la nature du langage.
 
 
  • Leur utilisation est très simple et sûre, et les problèmes liés à l’utilisation des threads (race conditions, deadlocks) sont évités.

Comment les utiliser ? 

Le principe est simple. On instancie un objet de type Worker, en lui passant en paramètre le script à exécuter en arrière-plan. 

La communication entre les workers est réalisée via l’envoi de messages, exploitable en utilisant des événements.

Par exemple :

Le code ci-dessous créé un worker à partir du script heavy-computation.js.

L’appel de la méthode postMessage permet d’envoyer une valeur primitive ou un objet.

Le message est ensuite récupérable dans le fichier heavy-computation.js, en utilisant onmessage :

Il est également plus pertinent de déplacer la fonction dans le script heavy-computation.js.

On peut envoyer un message au script de retour avec la fonction postMessage :

Remarque : postMessage est accessible globalement, et peut donc en théorie être situé n’importe où.

On intercepte le message dans le script principal via l’objet worker déclaré précédemment :

La gestion des erreurs 

Elle est réalisée, en utilisant l’attribut onerror via l’objet worker, au sein du script parent : 

L’objet retourné en cas d’erreur contiendra un message d’erreur, le nom de fichier ainsi que le numéro de ligne.

Un worker peut être arrêté simplement depuis le script parent avec terminate :

Les particularités 

Le partage des données : 

Les workers ont chacun leur propre contexte d’exécution, et les données envoyées par messages sont clonés. Chaque worker aura donc sa version d’un même objet (qui sera aussi différente du script principal).

L’ accès au DOM : 

Il n’est pas possible au sein d’un worker de modifier directement le DOM, ou d’accéder aux éléments de la page : 

L’importance de scripts depuis le worker : 

Il est possible d’importer des scripts, en utilisant la fonction globale importScript() : 

Conclusion 

Les web workers sont une solution simple et facile à mettre en place. Nous verrons par la suite comment les utiliser côté serveur (Node JS) et les exploiter dans des cas concrets. 

À très bientôt 

Leave a Reply

Your email address will not be published. Required fields are marked *