Le javascript en multithread? Oui, avec les Web Workers!

 

web_workers3

Historiquement, le javascript est un langage s'exécutant dans un environnement mono-thread (c'est-à-dire que tous les événements s'effectuent les uns après les autres). Lorsque une fonction longue était réalisée, l'interface graphique ne répondait plus, tout était figé. Cela est particulièrement gênant dans le cas où des animations ont lieu, ou si une vidéo est en cours de lecture.

Je vais vous présenter dans ce billet la solution qui a été trouvée pour répondre à ce problème : l'introduction des normes HTML5 et plus particulièrement les "Web Workers".

Les Web Workers

Les Web Workers fournissent un moyen simple d'exécuter des scripts dans des threads en arrière-plan d'un contenu web. Le thread worker peut réaliser des tâches sans interférer avec l'interface utilisateur. Une fois créé, un worker peut envoyer des messages à son thread parent par l'intermédiaire du gestionnaire d'événement précisé dans la suite de l'article.

Pour définir un worker, c'est très simple, il suffit de le déclarer de cette façon:

var worker = new Worker("worker.js");

En effet, un worker doit être défini dans son propre fichier.

A partir de la référence worker il est possible d'envoyer des messages au worker grâce à la méthode postMessage et récupérer les réponses grâce à l’événement onmessage. Il est également possible d’arrêter le worker avant la fin de son traitement (si les données d'entrée ont changé et que le calcul n'est plus nécessaire par exemple) grâce à la merthode terminate

main.js:

var worker = new Worker("worker.js"); // Déclaration du worker

buttonStart.onclick = function(){ 
   worker.postMessage(['param','keep']); // Envoie un message au worker
}

buttonStop.onclick = function(){ 
   worker.terminate(); // Arrête le worker immédiatement
}

// Événement lancé lorsque le worker a fini sa tâche.
worker.onmessage = function(e) {
  console.log('Message reçu du worker: ' + e.data); // Affiche le résultat renvoyé par le worker
}

Ce message sera reçu et traité par le worker grâce à l’événement onmessage:

worker.js:
self.onmessage = function(e) {
   console.log('Message reçu:' + e.data[0]); //Affiche param1
   //Traitement lourd nécessitant l'appel à thread

   var resultat = 42; //Resultat de notre calcul coûteux
   postMessage(resultat); //Envoie la réponse à notre thread principal
   if(e.data[1] == 'stop'){ 
      /*
       * Termine le worker, il ne traitera plus de nouveaux messages. 
       * Si le worker a pour but d'être utilisé plusieurs fois, il vaut mieux le garder ouvert.
       */
      close();
   }
}

Ce type de worker est donc très facile à mettre en place.

Limitations

Il n'y a pas de limitation en nombre de worker maximum pour une page web. Cependant, il est important de noter qu'un trop grand nombre de workers peuvent affecter les performances (notamment sur les mobiles), ainsi que la maintenabilité du code. En effet, Si un trop grand nombre de workers est défini, il peut devenir difficile de debugger car le workflow général de la page sera compliqué.
Les Web workers sont donc à utiliser avec précaution, et leur usage doit être limité aux sites web présentant des animations et/ou des traitements lourds (Par exemple un jeu HTML5).

Un commentaire

  1. Enfin, ça fait longtemps que je cherchais une solution à cela. En effet, avec le javascript, lorsque une fonction longue était réalisée, l’interface graphique ne répond plus et tout se figé. Je vais essayé ce Web Workers immédiatement.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.