JavaScript ne contient pas de threads, du moins dans sa forme actuelle. Qu'est-ce que vous essayez de faire exactement?
Eric Pohl
3
Pouvez-vous changer la réponse acceptée par celle-ci? stackoverflow.com/a/30891727/2576706 Il est beaucoup plus développé pour les futurs utilisateurs ..
En dehors de Gears, il n'y a rien de disponible pour le moment, mais il y a beaucoup de discussions sur la façon de l'implémenter, alors je suppose que regarder cette question car la réponse changera sans doute à l'avenir.
Voici la documentation pertinente pour Gears: API WorkerPool
WHATWG a un projet de recommandation pour les threads de travail: Web Workers
Chrome a intégré Gears, il peut donc créer des threads, bien qu'il nécessite une invite de confirmation de la part de l'utilisateur (et qu'il utilise une API différente pour les travailleurs Web, bien qu'il fonctionnera dans n'importe quel navigateur avec le plug-in Gears installé):
Démo de Google Gears WorkerPool (ce n'est pas un bon exemple car il s'exécute trop vite pour être testé dans Chrome et Firefox, bien qu'IE l'exécute assez lentement pour le voir bloquer l'interaction)
IE8 et IE9 ne peuvent faire des threads qu'avec le plugin Gears installé
Bien que Safari 4 prenne en charge les web workers, il semble que seul Firefox supporte le passage d'objets complexes via postMessage: hacks.mozilla.org/2009/07/working-smarter-not-harder Voir le dernier paragraphe de cet article sur l'utilisation du monde réel dans le projet Bespin pour des liens vers un shim pour qui implémente l'API Worker en termes de Google Gears et qui ajoute les fonctionnalités manquantes à l'implémentation worker de Safari 4 et des détails sur la façon dont ils ont implémenté des événements personnalisés transparents au-dessus de l'interface postMessage.
Sam Hasler le
6
Maintenant que IE9 est sorti, vous pouvez mettre à jour "IE8 ne peut faire des threads avec le plugin Gears installé" vers "IE8 et IE9 ne peut faire des threads qu'avec le plugin Gears installé"
BenoitParis
2
@ inf3rno pour avoir effectué de longs calculs sur un autre thread afin de ne pas ralentir l'interface utilisateur du navigateur.
Sam Hasler
6
@SamHasler Vous voudrez peut-être réviser votre réponse. Les agents Web sont désormais pris en charge par tous les navigateurs de bureau modernes. Voir aussi caniuse.com/#search=worker
Rob W
2
@SamHasler, il convient également de noter que Google Gears n'est plus pris en charge.
skeggse
73
Différentes façons de faire du multi-threading et asynchrone en JavaScript
Avant HTML5, JavaScript n'autorisait l'exécution que d'un fil par page.
Il y avait une certaine façon hacky pour simuler une exécution asynchrone avec rendement , setTimeout(), setInterval(), XMLHttpRequestou gestionnaires d'événements (voir la fin de ce post pour un exemple avec le rendement et setTimeout()).
Mais avec HTML5, nous pouvons désormais utiliser Worker Threads pour paralléliser l'exécution des fonctions. Voici un exemple d'utilisation.
Véritable multi-threading
Multi-threading: threads de travail JavaScript
HTML5 a introduit les threads Web Worker (voir: compatibilités des navigateurs )
Remarque: IE9 et les versions antérieures ne le prennent pas en charge.
Ces threads de travail sont des threads JavaScript qui s'exécutent en arrière-plan sans affecter les performances de la page. Pour plus d'informations sur Web Worker, lisez la documentation ou ce didacticiel .
Voici un exemple simple avec 3 threads Web Worker qui comptent jusqu'à MAX_VALUE et montrent la valeur calculée actuelle dans notre page:
//As a worker normally take another JavaScript file to execute we convert the function in an URL: http://stackoverflow.com/a/16799132/2576706function getScriptPath(foo){return window.URL.createObjectURL(newBlob([foo.toString().match(/^\s*function\s*\(\s*\)\s*\{(([\s\S](?!\}$))*[\s\S])/)[1]],{type:'text/javascript'}));}var MAX_VALUE =10000;/*
* Here are the workers
*///Worker 1var worker1 =newWorker(getScriptPath(function(){
self.addEventListener('message',function(e){var value =0;while(value <= e.data){
self.postMessage(value);
value++;}},false);}));//We add a listener to the worker to get the response and show it in the page
worker1.addEventListener('message',function(e){
document.getElementById("result1").innerHTML = e.data;},false);//Worker 2var worker2 =newWorker(getScriptPath(function(){
self.addEventListener('message',function(e){var value =0;while(value <= e.data){
self.postMessage(value);
value++;}},false);}));
worker2.addEventListener('message',function(e){
document.getElementById("result2").innerHTML = e.data;},false);//Worker 3var worker3 =newWorker(getScriptPath(function(){
self.addEventListener('message',function(e){var value =0;while(value <= e.data){
self.postMessage(value);
value++;}},false);}));
worker3.addEventListener('message',function(e){
document.getElementById("result3").innerHTML = e.data;},false);// Start and send data to our worker.
worker1.postMessage(MAX_VALUE);
worker2.postMessage(MAX_VALUE);
worker3.postMessage(MAX_VALUE);
Nous pouvons voir que les trois threads sont exécutés en simultanéité et affichent leur valeur actuelle dans la page. Ils ne gèlent pas la page car ils sont exécutés en arrière-plan avec des threads séparés.
Multi-threading: avec plusieurs iframes
Une autre façon d'y parvenir est d'utiliser plusieurs iframes , chacun exécutant un thread. Nous pouvons donner à l' iframe des paramètres par l'URL et l' iframe peut communiquer avec son parent afin d'obtenir le résultat et de le réimprimer (l' iframe doit être dans le même domaine).
Cet exemple ne fonctionne pas dans tous les navigateurs! Les iframes fonctionnent généralement dans le même thread / processus que la page principale (mais Firefox et Chromium semblent le gérer différemment).
Étant donné que l'extrait de code ne prend pas en charge plusieurs fichiers HTML, je vais simplement fournir les différents codes ici:
index.html:
//The 3 iframes containing the code (take the thread id in param)<iframe id="threadFrame1" src="thread.html?id=1"></iframe><iframe id="threadFrame2" src="thread.html?id=2"></iframe><iframe id="threadFrame3" src="thread.html?id=3"></iframe>//Divs that shows the result<div id="result1"></div><div id="result2"></div><div id="result3"></div><script>//This function is called by each iframefunction threadResult(threadId, result){
document.getElementById("result"+ threadId).innerHTML = result;}</script>
thread.html:
//Get the parameters in the URL: http://stackoverflow.com/a/1099670/2576706function getQueryParams(paramName){var qs = document.location.search.split('+').join(' ');var params ={}, tokens, re =/[?&]?([^=]+)=([^&]*)/g;while(tokens = re.exec(qs)){
params[decodeURIComponent(tokens[1])]= decodeURIComponent(tokens[2]);}return params[paramName];}//The thread code (get the id from the URL, we can pass other parameters as needed)var MAX_VALUE =100000;(function thread(){var threadId = getQueryParams('id');for(var i=0; i<MAX_VALUE; i++){
parent.threadResult(threadId, i);}})();
Simuler le multi-threading
Single-thread: émuler la concurrence JavaScript avec setTimeout ()
La manière `` naïve '' serait d'exécuter la fonction l' setTimeout()une après l'autre comme ceci:
setTimeout(function(){/* Some tasks */},0);
setTimeout(function(){/* Some tasks */},0);[...]
Mais cette méthode ne fonctionne pas car chaque tâche sera exécutée l'une après l'autre.
Nous pouvons simuler une exécution asynchrone en appelant la fonction de manière récursive comme ceci:
Comme vous pouvez le voir, cette deuxième méthode est très lente et fige le navigateur car elle utilise le thread principal pour exécuter les fonctions.
Single-thread: émuler la concurrence JavaScript avec rendement
Le rendement est une nouvelle fonctionnalité d' ECMAScript 6 , elle ne fonctionne que sur la version la plus ancienne de Firefox et Chrome (dans Chrome, vous devez activer le JavaScript expérimental apparaissant dans chrome: // flags / # enable-javascript-harmonie ).
Le mot-clé yield provoque la pause de l'exécution de la fonction de générateur et la valeur de l'expression qui suit le mot-clé yield est renvoyée à l'appelant du générateur. Il peut être considéré comme une version basée sur un générateur du mot-clé return.
Un générateur vous permet de suspendre l'exécution d'une fonction et de la reprendre plus tard. Un générateur peut être utilisé pour planifier vos fonctions avec une technique appelée trampoline .
Il n'y a pas de véritable threading en JavaScript. JavaScript étant le langage malléable qu'il est, vous permet d'en émuler une partie. Voici un exemple que j'ai rencontré l'autre jour.
Qu'entendez-vous par "vrai filetage"? Les fils verts sont de vrais fils.
Wes
10
Il n'y a pas de véritable multi-threading en Javascript, mais vous pouvez obtenir un comportement asynchrone en utilisant setTimeout()des requêtes AJAX asynchrones.
Voici juste un moyen de simuler le multi-threading en Javascript
Maintenant, je vais créer 3 threads qui calculeront l'addition des nombres, les nombres peuvent être divisés par 13 et les nombres peuvent être divisés par 3 jusqu'à 10000000000. Et ces 3 fonctions ne peuvent pas fonctionner en même temps que ce que signifie la concurrence. Mais je vais vous montrer une astuce qui fera exécuter ces fonctions de manière récursive dans le même temps: jsFiddle
Ce code m'appartient.
Partie du corps
<div class="div1"><input type="button" value="start/stop" onclick="_thread1.control ? _thread1.stop() : _thread1.start();"/><span>Counting summation of numbers till 10000000000</span> = <span id="1">0</span></div><div class="div2"><input type="button" value="start/stop" onclick="_thread2.control ? _thread2.stop() : _thread2.start();"/><span>Counting numbers can be divided with13 till 10000000000</span> = <span id="2">0</span></div><div class="div3"><input type="button" value="start/stop" onclick="_thread3.control ? _thread3.stop() : _thread3.start();"/><span>Counting numbers can be divided with3 till 10000000000</span> = <span id="3">0</span></div>
Partie Javascript
var _thread1 ={//This is my thread as object
control:false,//this is my control that will be used for start stop
value:0,//stores my result
current:0,//stores current number
func:function(){//this is my func that will runif(this.control){// checking for control to runif(this.current <10000000000){this.value +=this.current;
document.getElementById("1").innerHTML =this.value;this.current++;}}
setTimeout(function(){// And here is the trick! setTimeout is a king that will help us simulate threading in javascript
_thread1.func();//You cannot use this.func() just try to call with your object name},0);},
start:function(){this.control =true;//start function},
stop:function(){this.control =false;//stop function},
init:function(){
setTimeout(function(){
_thread1.func();// the first call of our thread},0)}};var _thread2 ={
control:false,
value:0,
current:0,
func:function(){if(this.control){if(this.current %13==0){this.value++;}this.current++;
document.getElementById("2").innerHTML =this.value;}
setTimeout(function(){
_thread2.func();},0);},
start:function(){this.control =true;},
stop:function(){this.control =false;},
init:function(){
setTimeout(function(){
_thread2.func();},0)}};var _thread3 ={
control:false,
value:0,
current:0,
func:function(){if(this.control){if(this.current %3==0){this.value++;}this.current++;
document.getElementById("3").innerHTML =this.value;}
setTimeout(function(){
_thread3.func();},0);},
start:function(){this.control =true;},
stop:function(){this.control =false;},
init:function(){
setTimeout(function(){
_thread3.func();},0)}};
_thread1.init();
_thread2.init();
_thread3.init();
Vous pouvez utiliser Narrative JavaScript , un compilateur qui transforme votre code en machine à états, vous permettant ainsi d'émuler le threading. Il le fait en ajoutant un opérateur «céder» (noté «->») au langage qui vous permet d'écrire du code asynchrone dans un seul bloc de code linéaire.
En Javascript brut, le mieux que vous puissiez faire est d'utiliser les quelques appels asynchrones (xmlhttprequest), mais ce n'est pas vraiment du threading et très limité. Google Gears ajoute un certain nombre d'API au navigateur, dont certaines peuvent être utilisées pour la prise en charge des threads.
Si vous ne pouvez ou ne voulez pas utiliser de trucs AJAX, utilisez un iframe ou dix! ;) Vous pouvez exécuter des processus dans des iframes en parallèle avec la page maître sans vous soucier des problèmes comparables entre navigateurs ou des problèmes de syntaxe avec dot net AJAX, etc., et vous pouvez appeler le JavaScript de la page maître (y compris le JavaScript qu'elle a importé) à partir d'un iframe.
Par exemple, dans un iframe parent, pour appeler egFunction()le document parent une fois le contenu iframe chargé (c'est la partie asynchrone)
parent.egFunction();
Générez également dynamiquement les iframes pour que le code html principal en soit libre si vous le souhaitez.
Cette description était un peu trop brève à mon goût. Pourriez-vous expliquer comment utiliser cette technique ou publier un lien vers un didacticiel montrant du code?
oligofren
3
Une autre méthode possible consiste à utiliser un interpréteur javascript dans l'environnement javascript.
En créant plusieurs interpréteurs et en contrôlant leur exécution à partir du thread principal, vous pouvez simuler le multi-threading avec chaque thread s'exécutant dans son propre environnement.
L'approche est quelque peu similaire à celle des travailleurs Web, mais vous donnez à l'interpréteur l'accès à l'environnement global du navigateur.
Javascript n'a pas de threads, mais nous avons des workers.
Les ouvriers peuvent être un bon choix si vous n'avez pas besoin d'objets partagés.
La plupart des implémentations de navigateur répartiront en fait les travailleurs sur tous les cœurs, ce qui vous permettra d'utiliser tous les cœurs. Vous pouvez voir une démo de ceci ici .
J'ai développé une bibliothèque appelée task.js qui rend cela très facile à faire.
task.js Interface simplifiée pour exécuter du code gourmand en ressources processeur sur tous les cœurs (node.js et web)
Un exemple serait
function blocking (exampleArgument){// block thread}// turn blocking pure function into a worker taskconst blockingAsync = task.wrap(blocking);// run task on a autoscaling worker pool
blockingAsync('exampleArgumentValue').then(result =>{// do something with result});
Avec la spécification HTML5, vous n'avez pas besoin d'écrire trop de JS pour le même ou de trouver des hacks.
L'une des fonctionnalités introduites dans HTML5 est Web Workers, qui exécute JavaScript en arrière-plan, indépendamment des autres scripts, sans affecter les performances de la page.
Il est pris en charge dans presque tous les navigateurs:
Réponses:
Consultez http://caniuse.com/#search=worker pour obtenir les informations d'assistance les plus récentes.
Ce qui suit était l'état du soutien vers 2009.
Les mots que vous souhaitez rechercher sur Google sont des threads de travail JavaScript
En dehors de Gears, il n'y a rien de disponible pour le moment, mais il y a beaucoup de discussions sur la façon de l'implémenter, alors je suppose que regarder cette question car la réponse changera sans doute à l'avenir.
Voici la documentation pertinente pour Gears: API WorkerPool
WHATWG a un projet de recommandation pour les threads de travail: Web Workers
Et il y a aussi les threads de travail DOM de Mozilla
Mise à jour: juin 2009, état actuel du support du navigateur pour les threads JavaScript
Firefox 3.5 a des web workers. Quelques démos de web workers, si vous voulez les voir en action:
Le plugin Gears peut également être installé dans Firefox.
Safari 4 et les nightlies WebKit ont des threads de travail:
Chrome a intégré Gears, il peut donc créer des threads, bien qu'il nécessite une invite de confirmation de la part de l'utilisateur (et qu'il utilise une API différente pour les travailleurs Web, bien qu'il fonctionnera dans n'importe quel navigateur avec le plug-in Gears installé):
IE8 et IE9 ne peuvent faire des threads qu'avec le plugin Gears installé
la source
Différentes façons de faire du multi-threading et asynchrone en JavaScript
Avant HTML5, JavaScript n'autorisait l'exécution que d'un fil par page.
Il y avait une certaine façon hacky pour simuler une exécution asynchrone avec rendement ,
setTimeout()
,setInterval()
,XMLHttpRequest
ou gestionnaires d'événements (voir la fin de ce post pour un exemple avec le rendement etsetTimeout()
).Mais avec HTML5, nous pouvons désormais utiliser Worker Threads pour paralléliser l'exécution des fonctions. Voici un exemple d'utilisation.
Véritable multi-threading
Multi-threading: threads de travail JavaScript
HTML5 a introduit les threads Web Worker (voir: compatibilités des navigateurs )
Remarque: IE9 et les versions antérieures ne le prennent pas en charge.
Ces threads de travail sont des threads JavaScript qui s'exécutent en arrière-plan sans affecter les performances de la page. Pour plus d'informations sur Web Worker, lisez la documentation ou ce didacticiel .
Voici un exemple simple avec 3 threads Web Worker qui comptent jusqu'à MAX_VALUE et montrent la valeur calculée actuelle dans notre page:
Nous pouvons voir que les trois threads sont exécutés en simultanéité et affichent leur valeur actuelle dans la page. Ils ne gèlent pas la page car ils sont exécutés en arrière-plan avec des threads séparés.
Multi-threading: avec plusieurs iframes
Une autre façon d'y parvenir est d'utiliser plusieurs iframes , chacun exécutant un thread. Nous pouvons donner à l' iframe des paramètres par l'URL et l' iframe peut communiquer avec son parent afin d'obtenir le résultat et de le réimprimer (l' iframe doit être dans le même domaine).
Cet exemple ne fonctionne pas dans tous les navigateurs! Les iframes fonctionnent généralement dans le même thread / processus que la page principale (mais Firefox et Chromium semblent le gérer différemment).
Étant donné que l'extrait de code ne prend pas en charge plusieurs fichiers HTML, je vais simplement fournir les différents codes ici:
index.html:
thread.html:
Simuler le multi-threading
Single-thread: émuler la concurrence JavaScript avec setTimeout ()
La manière `` naïve '' serait d'exécuter la fonction l'
setTimeout()
une après l'autre comme ceci:Mais cette méthode ne fonctionne pas car chaque tâche sera exécutée l'une après l'autre.
Nous pouvons simuler une exécution asynchrone en appelant la fonction de manière récursive comme ceci:
Comme vous pouvez le voir, cette deuxième méthode est très lente et fige le navigateur car elle utilise le thread principal pour exécuter les fonctions.
Single-thread: émuler la concurrence JavaScript avec rendement
Le rendement est une nouvelle fonctionnalité d' ECMAScript 6 , elle ne fonctionne que sur la version la plus ancienne de Firefox et Chrome (dans Chrome, vous devez activer le JavaScript expérimental apparaissant dans chrome: // flags / # enable-javascript-harmonie ).
Un générateur vous permet de suspendre l'exécution d'une fonction et de la reprendre plus tard. Un générateur peut être utilisé pour planifier vos fonctions avec une technique appelée trampoline .
Voici l'exemple:
la source
Avec les "side-specs" HTML5, plus besoin de pirater javascript avec setTimeout (), setInterval (), etc.
HTML5 & Friends présente la spécification javascript Web Workers . C'est une API pour exécuter des scripts de manière asynchrone et indépendante.
Liens vers la spécification et un tutoriel .
la source
Il n'y a pas de véritable threading en JavaScript. JavaScript étant le langage malléable qu'il est, vous permet d'en émuler une partie. Voici un exemple que j'ai rencontré l'autre jour.
la source
Il n'y a pas de véritable multi-threading en Javascript, mais vous pouvez obtenir un comportement asynchrone en utilisant
setTimeout()
des requêtes AJAX asynchrones.Qu'essayez-vous d'accomplir exactement?
la source
Voici juste un moyen de simuler le multi-threading en Javascript
Maintenant, je vais créer 3 threads qui calculeront l'addition des nombres, les nombres peuvent être divisés par 13 et les nombres peuvent être divisés par 3 jusqu'à 10000000000. Et ces 3 fonctions ne peuvent pas fonctionner en même temps que ce que signifie la concurrence. Mais je vais vous montrer une astuce qui fera exécuter ces fonctions de manière récursive dans le même temps: jsFiddle
Ce code m'appartient.
Partie du corps
Partie Javascript
J'espère que cette façon sera utile.
la source
Vous pouvez utiliser Narrative JavaScript , un compilateur qui transforme votre code en machine à états, vous permettant ainsi d'émuler le threading. Il le fait en ajoutant un opérateur «céder» (noté «->») au langage qui vous permet d'écrire du code asynchrone dans un seul bloc de code linéaire.
la source
Le nouveau moteur v8 qui devrait sortir aujourd'hui le soutient (je pense)
la source
En Javascript brut, le mieux que vous puissiez faire est d'utiliser les quelques appels asynchrones (xmlhttprequest), mais ce n'est pas vraiment du threading et très limité. Google Gears ajoute un certain nombre d'API au navigateur, dont certaines peuvent être utilisées pour la prise en charge des threads.
la source
Si vous ne pouvez ou ne voulez pas utiliser de trucs AJAX, utilisez un iframe ou dix! ;) Vous pouvez exécuter des processus dans des iframes en parallèle avec la page maître sans vous soucier des problèmes comparables entre navigateurs ou des problèmes de syntaxe avec dot net AJAX, etc., et vous pouvez appeler le JavaScript de la page maître (y compris le JavaScript qu'elle a importé) à partir d'un iframe.
Par exemple, dans un iframe parent, pour appeler
egFunction()
le document parent une fois le contenu iframe chargé (c'est la partie asynchrone)Générez également dynamiquement les iframes pour que le code html principal en soit libre si vous le souhaitez.
la source
Une autre méthode possible consiste à utiliser un interpréteur javascript dans l'environnement javascript.
En créant plusieurs interpréteurs et en contrôlant leur exécution à partir du thread principal, vous pouvez simuler le multi-threading avec chaque thread s'exécutant dans son propre environnement.
L'approche est quelque peu similaire à celle des travailleurs Web, mais vous donnez à l'interpréteur l'accès à l'environnement global du navigateur.
J'ai fait un petit projet pour le démontrer .
Une explication plus détaillée dans ce billet de blog .
la source
Javascript n'a pas de threads, mais nous avons des workers.
Les ouvriers peuvent être un bon choix si vous n'avez pas besoin d'objets partagés.
La plupart des implémentations de navigateur répartiront en fait les travailleurs sur tous les cœurs, ce qui vous permettra d'utiliser tous les cœurs. Vous pouvez voir une démo de ceci ici .
J'ai développé une bibliothèque appelée task.js qui rend cela très facile à faire.
Un exemple serait
la source
Avec la spécification HTML5, vous n'avez pas besoin d'écrire trop de JS pour le même ou de trouver des hacks.
L'une des fonctionnalités introduites dans HTML5 est Web Workers, qui exécute JavaScript en arrière-plan, indépendamment des autres scripts, sans affecter les performances de la page.
Il est pris en charge dans presque tous les navigateurs:
Chrome - 4.0+
IE - 10.0+
Mozilla - 3.5+
Safari - 4.0+
Opera - 11.5+
la source