Maison >interface Web >js tutoriel >Recherche sur l'API multithread des travailleurs Web dans les compétences JavaScript_javascript
HTML5 prend en charge des API telles que Web Worker, permettant aux pages Web d'exécuter du code multithread en toute sécurité. Cependant, Web Worker est en réalité soumis à de nombreuses limitations, car il ne peut pas réellement partager les données de la mémoire et ne peut envoyer des notifications d'état que par le biais de messages. Il ne peut donc même pas être qualifié de "multi-threading" au vrai sens du terme.
L'interface de Web Worker est très peu pratique à utiliser. Elle est essentiellement livrée avec un bac à sable, exécute un fichier js indépendant dans le bac à sable et communique avec le thread principal via postMessage et onMessage :
Les résultats obtenus peuvent constater que l'identifiant des données obtenues dans le thread a augmenté, mais après leur renvoi, l'identifiant dans le bundle du thread principal n'a pas changé. Par conséquent, l'objet passé dans le thread. est en fait copié, donc si c'est le cas, les threads ne partagent pas de données et évitent les conflits de lecture et d'écriture, donc c'est sûr. Le prix à payer pour garantir la sécurité des threads est de limiter la capacité de manipuler les objets du thread principal dans le thread.
Un mécanisme multithread aussi limité est très peu pratique à utiliser. Nous espérons certainement que Worker pourra donner l'impression que le code a la capacité de faire fonctionner plusieurs threads en même temps. Par exemple, prendre en charge un code qui ressemble au . suivant :
worker.run(function(bundle){
//faire quelque chose dans le thread de travail...
This.runOnUiThread(function(bundle /*shared obj*/){
//faire quelque chose dans le fil de discussion principal de l'interface utilisateur...
});
//...
});
Dans ce code, après avoir démarré un travailleur, nous pouvons laisser n'importe quel code s'exécuter dans le travailleur, et lorsque nous devons faire fonctionner le thread de l'interface utilisateur (comme la lecture et l'écriture du DOM), nous pouvons revenir au thread principal pour l'exécution. via this.runOnUiThread.
Alors comment mettre en œuvre ce mécanisme ? Regardez le code ci-dessous :
var self = ceci;
This._worker.onmessage = function(evt){
var ret = evt.data;
Si(ret.__UI_TASK__){
//exécuter sur la tâche d'interface utilisateur
var fn = (new Function("return " ret.__UI_TASK__))();
fn(ret.sharedObj);
}autre{
self.sharedObj = ret.sharedObj;
self._completes[ret.taskId](ret);
>
>
>
WorkerThread.prototype.run = function (tâche, terminée){
var _task = {__THREAD_TASK__:task.toString(), sharedObj : this.sharedObj, taskId : this._task_id};
This._completes[this._task_id ] = complet;
This._worker.postMessage(_task);
>
Le code ci-dessus définit un objet ThreadWorker, qui crée un Web Worker qui exécute thread.js, enregistre l'objet partagé SharedObj et traite les messages renvoyés par thread.js.
Si un message UI_TASK est renvoyé par thread.js, alors exécutez la fonction passée par le message, sinon exécutez le rappel complet de run Voyons comment thread.js est écrit :
if(data && data.__THREAD_TASK__){
var tâche = data.__THREAD_TASK__;
essayez{
var fn = (new Function("return " task))();
var ctx = {
filSignal : vrai,
sommeil : fonction (intervalle) {
ctx.threadSignal = false;
setTimeout(_run, interval);
},
runOnUiThread : fonction (tâche){
PostMessage({__UI_TASK__:task.toString(), sharedObj:data.sharedObj});
}
}
fonction _run(){
ctx.threadSignal = true;
var ret = fn.call(ctx, data.sharedObj);
PostMessage({error:null, returnValue:ret, __THREAD_TASK__:task, sharedObj:data.sharedObj, taskId: data.taskId});
}
_run(0);
}attraper(ex){
PostMessage({error:ex.toString(), returnValue:null, sharedObj: data.sharedObj});
>
>
>
Comme vous pouvez le voir, thread.js reçoit des messages du thread ui, dont le plus important est THREAD_TASK, qui est la "tâche" transmise par le thread ui qui doit être exécutée par le thread de travail depuis la fonction. n'est pas sérialisable, ce qui est transmis est une chaîne. Le thread de travail analyse la chaîne dans une fonction pour exécuter la tâche soumise par le thread principal (notez que l'objet partagé sharedObj est transmis dans la tâche une fois l'exécution terminée). le résultat du retour est transmis au thread ui via le message. Regardons de plus près. En plus de la valeur de retour returnValue, l'objet partagé sharedObj sera également renvoyé lors du renvoi, puisque le thread de travail et le thread ui ne partagent pas d'objets, nous synchronisons artificiellement les objets des deux côtés. devoir (ce fil de discussion est-il sûr ? ? Pourquoi ? )
Vous pouvez voir que l'ensemble du processus n'est pas compliqué. Après cette implémentation, ce ThreadWorker peut être utilisé des deux manières suivantes :
setInterval(function(){
t1.run(function(sharedObj){
return sharedObj.i ;
},
fonction(r){
console.log("t1>" r.returnValue ":" r.error);
>
);
}, 500);
var t2 = nouveau WorkerThread({i : 50});
t2.run(function(sharedObj){
pendant que(this.threadSignal){
sharedObj.i ;
this.runOnUiThread(function(sharedObj){
W("body ul").appendChild("
this.sleep(500);
>
return sharedObj.i;
}, fonction(r){
console.log("t2>" r.returnValue ":" r.error);
});
样的用法从形式和语义上来说都让代码具有良好的结构,灵活性和可维护性。
好了,关于Web Worker的用法探讨就介绍到这里,有兴趣的同学可以去看一下这个项目:https://github.com/akira-cn/WorkerThread. js (pour Worker 需要用服务器测试,我特意在项目中放了一个山寨的httpd.js,是个非常简陋的http服务的js,直接用node就可以跑起来)。