Les Web Workers sont un mécanisme/API grâce auquel les instructions d'un script peuvent être exécutés dans un thread parallèle au thread d'exécution principal d'une application web.
De ce fait il est possible de les utiliser pour les traitements lourds/long potentiellement bloquant, permettant de ne pas bloquer le thread principal et donc que la page ne freeze pas.
La vous me dite
Mais les fonction eval(), setTimeout() et setInterval() ne créent pas déjà un thread parallèle ?
- eval() : il faut savoir que cette fonction peut retourner une valeur de retour(définie par le code parsé) donc non multi-thread
- setTimeout() : se retrouve dans la zone de l’interprétation des événements
- setInterval() : se retrouve dans la zone de l’interprétation des événements
Limitations
Et oui tout grand pouvoir qu'il soit le multithreading Javascript à des limitation par souci de sécurité d'accès aux données navigateur un Worker n'à pas accès à :
un Worker à accès en lecture seulement :
|
Initialisation
En premier lieux nous allons utiliser la méthode Worker() pour créer un web worker;
Un Worker pouvant en créer un autre je parlerait donc par la suite de parent pour l'appelant pour ne pas se limiter au thread principal
Les Workers sont crées avec le code venant d'un fichier javascript que celui-ci vas charger puis exécuter, si vous souhaiter exécuter du code écris dans un fichier déjà chargé vous devrez créer un objet Blob et passer à la méthode Worker() l'URL de ce Blob. Pour les URL relative depuis un code exécuté en thread principal le chemin relatif est depuis le dossier de la page, depuis un Worker c'est depuis le dossier dans lequel est son fichier et pour du code d'un Blob les chemins relatifs sont caducs |
Code Javascript : | Sélectionner tout |
worker = Worker("myworker.js")
Comme vous pouvez le voir sur l'image à droite de ce texte pour la communication avec le tread il faut utiliser la commande postMessage() et les données envoyées peuvent être de n'importe quel format(String, Number, Object, Array, ...) Pour vous expliquer comment procéder rien de mieux qu'un petit exemple coté parent:
coté worker.js:
|
Imaginons que votre Worker soit pour du traitement plutôt lourd et que pour des raisons évidente de maintenabilité(les fichier de plus de 500 lignes ça commence à poser soucis ^^)
vous le scindé en plusieurs fichier, et bien pas de soucis, la fonction importScripts() est la !
Pour les URL relatives c'est depuis le dossier dans lequel est le fichier du Worker et pour du code d'un Blob les chemins relatifs sont caducs |
Code Javascript : | Sélectionner tout |
1 2 3 | importScripts(); /* Importe strictement rien */ importScripts('foo.js'); /* Importe "foo.js" */ importScripts('foo.js', 'bar.js'); /* Importe les 2 scripts */ |
Suicide ou meurtre ?
Pour arrêter un Web Worker vous avez 2 solutions
- La méthode douce avec close() depuis le Worker
- la méthode musclée depuis le parent avec objetworker.terminate()
Conclusion
Il n'est donc pas difficile de mettre en place des Web Workers, le plus compliqué étant de faire bien attention au traitement des données envoyées en message.
De plus voici une petite recommandation: n'en abusez pas sauf si c'est vôtre trip de faire freezer les pc chargeant votre page web
Il existe aussi une version partagée des Web Workers(pour plusieurs pages en même temps) mais comme il on un degré de complexité plus important je les aborderait dans un prochain article
Source MDN