Maison >interface Web >js tutoriel >Utiliser Multi-Thread en Javascript - Pas à propos de WebWorkers ni de WebAssembly
Il est bien connu que JavaScript s'exécute sur un seul thread. Ce concept est si intégral que nous y faisons souvent référence par son nom - le Main Thread. Alors, cela signifie-t-il que votre processeur multicœur est inutile lorsque vous exécutez JavaScript ?
Pas tout à fait.
JavaScript peut être un peu effronté, envoyant des messages contradictoires sur ses fils de discussion.
Mais même sans approfondir des fonctionnalités plus complexes telles que Web Workers et WebAssembly, JavaScript de base peut utiliser des flux de travail multithread.
Pour être clair, cet article se concentre sur le JavaScript basé sur un navigateur Web. D'autres environnements, comme Node.js, peuvent gérer les choses différemment.
Nous allons explorer les options pour les opérations multithread et de type multithread en JavaScript. La réalité est que vous pouvez et devez utiliser des flux de travail multithread dans du JavaScript de base purement vanille.
Heureux de.
JavaScript est un langage monothread, mais il est interprété par les navigateurs Web - et les navigateurs sont des logiciels multithread.
Il existe plusieurs méthodes pour simuler et utiliser le multithreading, et vous les utilisez peut-être sans même vous en rendre compte.
De plus, JavaScript se comporte souvent d'une manière qui semble multithread sans l'être en réalité. Cela peut ressembler à de la triche, mais cela offre effectivement les avantages que nous attendons d'un comportement multithread.
JavaScript est un système basé sur les événements. Lorsque le navigateur traite un fichier JavaScript, il exécute tout le code qu'il contient. Il est tout à fait possible d'écrire du code qui ne s'arrête pas - même si c'est généralement une mauvaise idée car cela peut faire planter le navigateur.
Ce que nous faisons habituellement, c'est configurer des auditeurs d'événements et attendre que quelque chose se produise. À ce stade, JavaScript est complètement inactif. Cette attente inactive ne serait pas possible sans décharger une partie du travail du fil principal.
Les événements eux-mêmes ne sont pas multithread, mais l'attente et la vérification des événements sont gérées par le navigateur, et non par JavaScript. Ce processus est déchargé du fil de discussion principal.
Des fonctions telles que setTimeout et setInterval existent depuis de nombreuses années. Ils déchargent le temps d'attente du fil principal.
Simplifions comment cela fonctionne. Dans les langages de niveau inférieur, les minuteries et l'attente sont souvent implémentées en vérifiant constamment « Est-il déjà temps ? » Imaginez une boucle while() qui vérifie le temps écoulé et continue lorsque le moment est venu. Les approches modernes peuvent utiliser des interruptions du processeur pour éviter de boucher le thread du processeur.
Cependant, lorsque vous utilisez setTimeout ou setInterval en JavaScript, le langage est complètement inactif pendant l'attente, ce qui, encore une fois, signifie que l'attente est traitée d'une manière ou d'une autre en dehors du fil principal.
De nos jours, nous recevons de plus en plus de fonctions et d'API asynchrones des navigateurs. L'API fetch est un exemple bien connu. Même les API les plus récentes, comme l'API Clipboard, sont asynchrones.
Cela signifie que vous demandez au navigateur d'effectuer une action, et il libère le fil principal de JavaScript (ou lui permet de traiter d'autres éléments - nous en parlerons plus tard) et vous avertit (en traitant le code suivant) lorsque c'est terminé.
Asynchrone ne signifie pas nécessairement multithread - pas toujours, pas directement. Mettre simplement le mot async devant une fonction ne fait rien pour vous.
Il existe deux éléments clés dans la manière dont JavaScript gère les comportements asynchrones :
Considérez la file d'attente de rappel comme une ligne de fonctions en attente d'exécution. Ces fonctions s'exécutent une par une dans le thread principal. Lorsqu'une opération asynchrone se termine - qu'il s'agisse d'un événement, d'un délai d'attente ou d'une récupération terminée - son rappel est placé dans cette file d'attente.
La boucle d'événements est responsable du déplacement des rappels de la file d'attente vers la pile d'appels lorsque la pile d'appels est vide.
Le navigateur Web prend le contrôle de certaines opérations et peut créer de nouveaux threads pour celles-ci, notamment des actions telles que fetch ou setTimeout. JavaScript n'a pas besoin de gérer ces threads. Lorsque l'opération asynchrone est terminée, le navigateur place le rappel correspondant dans la file d'attente de rappel et JavaScript continue l'exécution à partir de là.
Considérez ce code :
console.log('Start'); setTimeout(() => { console.log('This is asynchronous'); }); console.log('End');
Sortie :
Start End This is asynchronous
Voici ce qui se passe :
Remarquez qu'il manque le paramètre timeout à setTimeout. Il s'agit d'une technique courante pour différer l'exécution de code de priorité inférieure - traitez d'abord tout le reste, une fois cela fait, effectuez la chose « de priorité inférieure ».
Ce que cela fait, c'est placer immédiatement la fonction à l'intérieur de setTimeout dans la file d'attente de rappel, et elle s'exécute à la première occasion lorsque le thread principal est inactif.
requestAnimationFrame est une API de navigateur qui indique au navigateur que vous souhaitez exécuter du code juste avant qu'il calcule et mette à jour la vue (pensez-y en images par seconde dans les jeux vidéo).
Pour une raison quelconque, les développeurs Web ne pensent pas aux repaints et aux FPS, mais c'est comme ça que ça marche.
Il est intrinsèquement asynchrone (mais pas multithread).
L'utilisation de setTimeout sans heure spécifiée était souvent utilisée à des fins similaires avant l'introduction de requestAnimationFrame, même si elle était loin d'être aussi utile (juste mieux que rien).
Cette fonction met votre code en file d'attente dans une pile spéciale. Juste avant de restituer une nouvelle image (le repaint), le navigateur exécute ce code en file d'attente. C'est parfait pour apporter des modifications au DOM, au HTML ou au CSS (et seulement ceux-là, s'il vous plaît, je vous interdit de faire des calculs là-bas !).
Bien que cet article ne les concerne pas, il convient de mentionner que vous pouvez réaliser de véritables opérations multithread en utilisant Web Workers et WebAssembly. Ceux-ci vous permettent d'exécuter des scripts dans des threads en arrière-plan. Ils ne peuvent pas manipuler directement le DOM, mais ils sont inestimables pour traiter des tâches lourdes (calculs matriciels, ça vous dit ?). Cette approche est souvent utilisée dans les jeux basés sur HTML5 - les plus complexes, pas seulement le tic-tac-toe.
JavaScript, une fois isolé, reste monothread. Mais dans le monde réel, il s'agit d'un langage interprété fonctionnant dans les environnements multithread des navigateurs Web. Si votre interprète vous propose un coup de main, prenez-le et utilisez-le.
Cet article couvre beaucoup de choses : connaissances de base, explications de bas niveau, et plus encore. Mais c’est souvent ainsi que se déroule le développement : tous interconnectés. C'est pourquoi j'aime regarder la situation dans son ensemble ; parfois, une concentration détaillée n'est pas la solution à un problème.
Async vous a-t-il déjà causé des cauchemars de débogage ?
C'est certainement le cas - il y a quelques années, obtenir des piles contenant des erreurs n'était pas vraiment un problème.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!