Ahora es más fácil mover el trabajo pesado a subprocesos en segundo plano con los módulos de JavaScript en los trabajadores la toile.
JavaScript est à thread unique, ce qui signifie qu'il ne peut effectuer qu'une seule opération à la fois. Ceci est intuitif et fonctionne bien dans de nombreux cas sur le Web, mais cela peut être problématique lorsque nous devons effectuer des tâches lourdes telles que le traitement de données, l'analyse, le calcul ou l'analyse. À mesure que des applications de plus en plus complexes sont diffusées sur le Web, il existe un besoin accru de traitement multithread.
Sur la plate-forme Web, la principale primitive de threading et de parallélisme est le API de travail Web. Les ouvriers sont une abstraction légère en plus de threads du système d'exploitation que exponen un mensaje que pasa API para la comunicación entre subprocesos. Esto puede ser inmensamente útil cuando se realizan cálculos costosos o se opera en grandes conjuntos de datos, lo que permite que el hilo principal se ejecute sin problemas mientras se realizan las costosas operaciones en uno o más hilos en segundo plano.
Voici un exemple d'utilisation typique d'un worker, où un script worker écoute les messages du thread principal et répond en envoyant ses propres messages:
page.js:
const ouvrier = new Ouvrier('worker.js');
ouvrier.addEventListener(et => {
console.Journal(et.Les données);
});
ouvrier.postMessage('hello');
worker.js:
addEventListener('message', et => {
si (et.Les données === 'hello') {
postMessage('world');
}
});
La API de Web Worker ha estado disponible en la mayoría de los navigateurs durante más de diez años. Si bien eso significa que los trabajadores tienen un excelente soporte de le navigateur y están bien optimizados, también significa que son anteriores a los módulos de JavaScript. Dado que no existía un sistema de módulos cuando se diseñaron los trabajadores, la API para cargar código en un trabajador y componer scripts se ha mantenido similar a los enfoques de carga de scripts síncronos comunes en 2009.
Histoire: ouvriers classiques
Le constructeur Worker prend un script classique URL, que es relativa a la URL del documento. Inmediatamente devuelve una referencia a la nueva instancia de trabajador, que expone una interfaz de mensajería, así como una terminer ()
méthode qui arrête et détruit immédiatement le travailleur.
const ouvrier = new Ouvrier('worker.js');
UNE importScripts ()
La fonction est disponible dans les web workers pour charger du code supplémentaire, mais arrête l'exécution du worker pour rechercher et évaluer chaque script. Il exécute également des scripts dans la portée globale comme un classique. , ce qui signifie que les variables d'un script peuvent être écrasées par des variables d'un autre.
worker.js:
importScripts('greet.js');
addEventListener('message', et => {
postMessage(sayHello());
});
greetr.js:
une fonction sayHello() {
revenir 'world';
}
Pour cette raison, les web workers ont historiquement imposé un effet démesuré sur l'architecture d'une application. Les développeurs ont dû créer des outils et des solutions intelligents pour rendre possible l'utilisation de travailleurs Web sans renoncer aux pratiques de développement modernes. À titre d'exemple, des packages comme webpack incorporent une petite implémentation de chargeur de module dans le code généré qui utilise importScripts ()
pour le chargement de code, mais enveloppez les modules dans des fonctions pour éviter les collisions de variables et simuler les importations et exportations de dépendances.
Entrez les travailleurs du module
Un nouveau mode pour les travailleurs Web avec les avantages d'ergonomie et de performances de Modules JavaScript est livré dans Chrome 80, appelé module workers. Les
Ouvrier
le constructeur accepte maintenant un nouveau {type: "module"}
option, qui modifie le chargement et l'exécution du script pour qu'il corresponde .
const ouvrier = new Ouvrier('worker.js', {
taper: 'module'
});
Dado que los trabajadores de módulo son módulos de JavaScript estándar, pueden utilizar declaraciones de importación y exportación. Al igual que con todos los módulos de JavaScript, las dependencias solo se ejecutan una vez en un contexto dado (hilo principal, trabajador, etc.), y todas las importaciones futuras hacen referencia a la instancia del módulo ya ejecutada. Los navegadores también optimizan la carga y ejecución de módulos JavaScript. Las dependencias de un módulo se pueden cargar antes de que se ejecute el módulo, lo que permite cargar árboles de módulos completos en paralelo. La carga de módulos también almacena en cache el código analizado, lo que significa que los módulos que se utilizan en el hilo principal y en un trabajador solo necesitan analizarse una vez.
Le passage aux modules JavaScript permet également d'utiliser import dynamique pour un code de chargement paresseux sans bloquer l'exécution du worker. L'importation dynamique est beaucoup plus explicite que l'utilisation importScripts ()
pour charger les dépendances, car les exportations de modules importées sont renvoyées au lieu de s'appuyer sur des variables globales.
worker.js:
importer { sayHello } desde './greet.js';
addEventListener('message', et => {
postMessage(sayHello());
});
greetr.js:
importer greetings desde './data.js';
exportation une fonction sayHello() {
revenir greetings.hello;
}
Pour assurer de belles performances, l'ancien importScripts ()
La méthode n'est pas disponible dans le module workers. Changer les nœuds de calcul pour utiliser des modules JavaScript signifie que tout le code est chargé dans Mode strict. Un autre changement notable est que la valeur de Este
au niveau supérieur d'un module JavaScript est
indéfini
, mientras que en los trabajadores clásicos el valor es el portée global del trabajador. Afortunadamente, siempre ha habido una soi
global qui fournit une référence à la portée globale. Il est disponible pour tous les types de travailleurs, y compris les travailleurs de service, ainsi que le DOM.
Los trabajadores del módulo también eliminan la compatibilidad con comentarios de estilo HTML. ¿Sabía que puede utilizar comentarios HTML en scripts de trabajadores web?
Précharger les travailleurs avec modulepreload
Une amélioration substantielle des performances qui vient avec les travailleurs de module est la capacité de précharger les travailleurs et leurs dépendances. Avec les modules worker, les scripts sont chargés et exécutés comme des modules JavaScript standard, ce qui signifie qu'ils peuvent être préchargés et même pré-analysés à l'aide de modulepreload
:
<relier rel="modulepreload" href="worker.js"><scénario>
addEventListener('load', () => {
const ouvrier = new Ouvrier('worker.js', { taper: 'module' });
});
</scénario>
Les modules préchargés peuvent également être utilisés à la fois par le thread principal et les travailleurs du module. Ceci est utile pour les modules qui sont importés dans les deux contextes, ou dans les cas où il n'est pas possible de savoir à l'avance si un module sera utilisé dans le thread principal ou dans un worker.
Auparavant, les options disponibles pour le préchargement des scripts de travail Web étaient limitées et pas nécessairement fiables. Les nœuds de calcul classiques disposaient de leur propre type de ressource "worker" pour le préchargement, mais aucun navigateur n'a été implémenté . En conséquence, la principale technique disponible pour précharger les web workers était d'utiliser
, que se basó completamente en la caché HTTP. Cuando se usa en combinación con los en-têtes de almacenamiento en caché correctos, esto hizo posible evitar que la instanciación del trabajador tuviera que esperar para descargar el script del trabajador. Sin embargo, a diferencia de
modulepreload
cette technique ne prenait pas en charge le préchargement ou la pré-analyse des dépendances.
Qu'en est-il des travailleurs partagés?
Travailleurs partagés ont été mis à jour avec la prise en charge des modules JavaScript à partir de Chrome 83. Comme pour les collaborateurs dédiés, la création d'un collaborateur partagé avec le {type: "module"}
L'option charge désormais le script de travail en tant que module au lieu d'un script classique:
const ouvrier = new SharedWorker('/worker.js', {
taper: 'module'
});
Avant la compatibilité avec les modules JavaScript, SharedWorker ()
Le constructeur n'attendait qu'une seule URL et une seule option patate douce
argument. Cela continuera à fonctionner pour une utilisation classique du partage de nœuds de calcul; cependant, la création de modules de travail partagés nécessite l'utilisation du nouveau options
argument. Les Options disponibles
sont les mêmes que celles d'un travailleur dévoué, y compris patate douce
option qui remplace la précédente patate douce
argument.
Qu'en est-il du technicien de service?
La spécification du technicien de service a déjà été mis à jour pour prendre en charge l'acceptation d'un module JavaScript comme point d'entrée, en utilisant le même {type: "module"}
option en tant que module worker, mais ce changement n'a pas encore été implémenté dans les navigateurs. Une fois que cela se produit, il sera possible d'instancier un service worker à l'aide d'un module JavaScript à l'aide du code suivant:
navigateur.serviceWorker.S'inscrire('/sw.js', {
taper: 'module'
});
Maintenant que la spécification a été mise à jour, les navigateurs commencent à implémenter le nouveau comportement. Cela prend du temps car il existe des complications supplémentaires associées à l'incorporation de modules JavaScript dans le service worker. Le dossier du technicien de service doit comparer les scripts importés avec leurs versions précédentes en cache pour déterminer s'il faut déclencher une mise à jour, et cela doit être implémenté pour les modules JavaScript lorsqu'ils sont utilisés pour les techniciens de service. De plus, les travailleurs des services doivent être en mesure de ignorer le cache pour les scripts dans certains cas lors de la vérification des mises à jour.
Ressources supplémentaires et lectures complémentaires