Heim  >  Artikel  >  Web-Frontend  >  Ausführliche Erläuterung des Javascript-Multithreadings in HTML5

Ausführliche Erläuterung des Javascript-Multithreadings in HTML5

黄舟
黄舟Original
2017-03-25 16:10:252086Durchsuche

JavascriptAusführungsmechanismus
Vor HTML5 arbeitete JavaScript im Browser im Single-Thread-Verfahren, obwohl es viele Möglichkeiten gibt, eine Multi-Threading-Simulation zu implementieren (zum Beispiel: die setinterval-Methode, die setTimeout-Methode usw.) in Javascript, aber im Wesentlichen wird die Ausführung des Programms immer noch von der JavaScript-Engine in einer Single-Thread-Methode ausgeführt. . Der in HTML5 eingeführte Worker-Thread ermöglicht es der browserseitigen Javascript-Engine, gleichzeitig Javascript-Code auszuführen, wodurch eine gute Unterstützung für browserseitige Multithreading-Programmierung erreicht wird – WebWorker

Web Worker in HTML5 kann in zwei verschiedene Thread-Typen unterteilt werden, einer ist ein dedizierter Thread-Worker und der andere ist ein gemeinsamer Thread-Shared Worker
Dedizierter Web-Worker. Er kann mit anderen Workern oder Browserkomponenten kommunizieren,

, aber nicht mit dem DOM.

Dediziert bedeutet, dass dieser Thread in verschiedenen Mainstream-Browsern außer IE jeweils nur eine Anforderung verarbeitet. Einen Thread erstellenDas Erstellen eines Workers ist sehr einfach. Übergeben Sie einfach den Dateinamen der JavaScript-Datei, die im Thread ausgeführt werden muss, an den

Konstruktor

Das war’s .
Thread-Kommunikation
Zur Kommunikation zwischen dem Haupt-Thread und dem Sub-Thread werden die postMessage- und onmessage-Methoden des Thread-
-Objekts verwendet An wen werden die Daten gesendet? Der Absender verwendet die Methode „postMessage“ und der Empfänger verwendet nur einen Parameter, nämlich die übertragenen Daten. Wenn es sich um ein Ereignis handelt, ist dies der Fall .data erhält die empfangenen Daten

SendenJSON
Daten
JSON wird nativ von JS unterstützt Verwenden Sie JSON für komplexe Daten. Beispiel:

Fehlerbehandlung Wenn in einem Thread ein Fehler auftritt, wird dessen onerror-Ereignisrückruf aufgerufen. Der Umgang mit Fehlern ist also sehr einfach, nämlich das Einbinden des onerror-Ereignisses der Thread-Instanz. Diese Rückruffunktion verfügt über einen Parameter „error“, der aus drei Feldern besteht: „message“ – die Fehlermeldung; „filename“ – die Skriptdatei, in der der Fehler aufgetreten ist; „line“ – die Zeile, in der der Fehler aufgetreten ist.

postMessage({'cmd': 'init', 'timestamp': Date.now()});
Den Thread zerstören

Verwenden Sie innerhalb des Threads die Close-Methode, um sich selbst zu zerstören. Verwenden Sie im Hauptthread außerhalb des Threads die Terminate-Methode der Thread-Instanz, um den Thread zu zerstören.
HTML-Code:

Skriptdatei fibonacci.js-Code:

Legen Sie sie in dasselbe Verzeichnis, führen Sie die Auslagerungsdatei aus und In der Konsole können Sie die Ergebnisse des Vorgangs sehen.

Hier gibt es noch einen weiteren Punkt: Das Onmessage-Ereignis kann auf andere Weise eingebunden werden:

<script type="text/javascript">
  
onload
 = function(){
      var worker = 
new
 Worker(&#39;fibonacci.js&#39;);  
      worker.onmessage = function(event) {
        console.log("Result:" + event.data);
      };
      worker.onerror = function(error) {
        console.log("Error:" + error.message);
      };
      worker.postMessage(40);
  }  
  </script>

Ich persönlich halte es für sehr problematisch, daher ist es besser, Onmessage direkt zu verwenden .

//fibonacci.js
var fibonacci = function(n) {
    
return
 n < 2 ? n : arguments.c
all
ee(n - 1) + arguments.callee(n - 2);
};
onmessage = function(event) {
    var n = parseInt(event.data, 10);
    postMessage(fibonacci(n));
};
Andere Skriptdateien verwenden


Arbeitsthreads können die globale Methode importScripts verwenden, um andere Domänenskriptdateien oder

Klassenbibliotheken
worker.addEvent
List
ener(&#39;message&#39;, function(event) {
   console.log("Result:" + event.data);
}, false);
zu laden und zu verwenden. Folgende Methoden sind beispielsweise zulässig:

Nach dem Import können Sie die Methoden in diesen Dateien direkt verwenden. Schauen Sie sich ein kleines Beispiel im Internet an:
Einige Internetnutzer im Internet haben auch darüber nachgedacht, hier die importScripts-Methode zu verwenden, um das Problem des Ressourcen-Vorladens zu lösen (der Browser lädt die Ressource vor, ohne die Ressource zu analysieren und auszuführen). ). Der Grund ist auch sehr einfach.

Thread-Verschachtelung
importScripts();                        
importScripts(&#39;foo.js&#39;);                
importScripts(&#39;foo.js&#39;, &#39;bar.js&#39;);

Sie können auch Unterthreads im Arbeitsthread erstellen, und die verschiedenen Vorgänge sind immer noch dieselben.

mportScripts(&#39;math_utilities.js&#39;); 
 
 onmessage = function (event) 
 { 
   var first = event.data.first; 
   var second = event.data.second; 
   calculate(first,second); 
 }; 
 
 function calculate(first,second) { 
    //do the calculation work 
   var common_divisor=divisor(first,second); 
   var common_multiple=multiple(first,second); 
   postMessage("Work done! " + 
      "The least common multiple is " + common_divisor  +
      " and the greatest common divisor is "+common_multiple); 
 }

Synchronisierungsprobleme

Worker verfügt über keinen Sperrmechanismus und Multithread-Synchronisierungsprobleme können nur durch Code gelöst werden (z. B. durch das Definieren von Signalen Variablen
) .

共享型SharedWebWorker
  共享型web worker主要适用于多连接并发的问题。因为要处理多连接,所以它的API与专用型worker稍微有点区别。除了这一点,共享型web worker和专用型worker一样,不能访问DOM,并且对窗体属性的访问也受到限制。共享型web worker也不能跨越通信。
  页面脚本可以与共享型web worker通信,然而,与专用型web worker(使用了一个隐式的端口通信)稍微有点不同的是,通信是显式的通过使用一个端口(port)对象并附加上一个消息事件处理程序来进行的。

  在收到web worker脚本的首个消息之后,共享型web worker把一个事件处理程序附加到激活的端口上。一般情况下,处理程序会运行自己的postMessage()方法来把一个消息返回给调用代码,接着端口的start()方法生成一个有效的消息进程。
      看网上能找到的的唯一个例子:创建一个共享线程用于接收从不同连接发送过来的指令,然后实现自己的指令处理逻辑,指令处理完成后将结果返回到各个不同的连接用户。
HTML代码:

<script> 
  var worker = new SharedWorker(&#39;sharedworker.js&#39;); 
  var log = document.getElementByIdx_x_x_x_x(&#39;response_from_worker&#39;); 
  worker.port.addEventListener(&#39;message&#39;, function(e) { 
  //log the response data in web page 
  log.textContent =e.data; 
  }, false); 
  worker.port.start(); 
  worker.port.postMessage(&#39;ping from user web page..&#39;); 
  
  //following method will send user input to sharedworker 
  function postMessageToSharedWorker(input) 
  { 
  //define a json object to construct the request 
  var instructions={instruction:input.value}; 
  worker.port.postMessage(instructions); 
  } 
  </script>

 脚本文件代码:

 // 创建一个共享线程用于接收从不同连接发送过来的指令,指令处理完成后将结果返回到各个不同的连接用户。
 var connect_number = 0; 
 
 onconnect = function(e) { 
  connect_number =connect_number+ 1; 
  //get the first port here 
  var port = e.ports[0]; 
  port.postMessage(&#39;A new connection! The 
current
 connection number is &#39; 
  + connect_number); 
  port.onmessage = function(e) { 
   //get instructions from requester 
   var instruction=e.data.instruction; 
   var results=execute_instruction(instruction); 
    port.postMessage(&#39;Request: &#39;+instruction+&#39; Response &#39;+results 
      +&#39; from shared worker...&#39;); 
  }; 
 }; 
 function execute_instruction(instruction) 
 { 
 var result_value; 
 //implement your logic here 
 //execute the instruction... 
 return result_value;
 }

      在上面的共享线程例子中,在主页面即各个用户连接页面构造出一个共享线程对象,然后定义了一个方法 postMessageToSharedWorker 向共享线程发送来之用户的指令。同时,在共享线程的实现代码片段中定义 connect_number 用来记录连接到这个共享线程的总数。之后,用 onconnect 事件处理器接受来自不同用户的连接,解析它们传递过来的指令。最后,定义一个了方法 execute_instruction 用于执行用户的指令,指令执行完成后将结果返回给各个用户。

      这里我们并没有跟前面的例子一样使用到了工作线程的 onmessage 事件处理器,而是使用了另外一种方式 addEventListener。实际上,前面已经说过,这两种的实现原理基本一致,只是在这里有些稍微的差别,如果使用到了 addEventListener 来接受来自共享线程的消息,那么就要先使用 worker.port.start() 方法来启动这个端口。之后就可以像工作线程的使用方式一样正常的接收和发送消息

线程中能做的事
1.能使用setTimeout(), clearTimeout(), setInterval(),clearInterval()等函数。
2.能使用navigator对象。
3.能使用XMLHttpRequest来发送请求。
4.可以在线程中使用Web Storage。

5.线程中可以用self获取本线程的作用域。

线程中不能做的事
1.线程中是不能使用除navigator外的DOM/BOM对象,例如window,document(想要操作的话只能发送消息给worker创建者,通过回调函数操作)。
2.线程中不能使用主线程中的变量和函数。
3.线程中不能使用有"挂起"效果的操作命令,例如alert等。
4.线程中不能跨域加载JS。

线程也是需要消耗资源的,而且使用线程也会带来一定的复杂性,所以如果没有充足的理由来使用额外的线程的话,那么就不要用它。

Das obige ist der detaillierte Inhalt vonAusführliche Erläuterung des Javascript-Multithreadings in HTML5. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn