Home  >  Article  >  Web Front-end  >  Detailed explanation of Javascript multi-threading in HTML5

Detailed explanation of Javascript multi-threading in HTML5

黄舟
黄舟Original
2017-03-25 16:10:252115browse

JavascriptExecution mechanism
Before HTML5, JavaScript in the browser worked in a single-threaded manner, although there are many ways to implement multi-threading. Simulation (for example: setinterval method, setTimeout method in Javascript, etc.), but in essence, the running of the program is still performed by the JavaScript engine in a single-threaded manner. . The worker thread introduced in HTML5 allows the browser-side Javascript engine to execute Javascript code concurrently, thereby achieving good support for browser-side multi-threaded programming.

##Javascript. Multi-threading - WebWorker
The Web Worker in HTML5 can be divided into two different thread types, one is the dedicated thread Dedicated Worker and the other is the shared thread Shared Worker. Each type of thread has a different purpose.

Specialized web worker## A dedicated worker is connected to the script that created it. It can communicate with other workers or browser components,

but it cannot communicate with the DOM. Dedicated means that this thread only handles one requirement at a time in various mainstream browsers except IE. It has been implemented in the thread, you can use it with confidence.

Creating a thread
Creating a worker is very simple, just pass the file name of the JavaScript file that needs to be executed in the thread to the constructor
That’s it.
Thread communication

To communicate between the main thread and the child thread, the postMessage and onmessage methods of the threadobject
are used. Who sends data to whom? The sender uses the postMessage method, and the receiver uses the onmessage method to receive data. PostMessage has only one parameter, which is the data to be passed. Onmessage also has only one parameter. If it is an event, it is passed through the event. .data Gets the received data.
Send

JSON

Data JSON is something natively supported by JS. There is no need to use it. Use JSON for complex data. Teleport it. For example:

postMessage({'cmd': 'init', 'timestamp': Date.now()});

Handling errors

When an error occurs in a thread, its onerror event callback will be called. So the way to handle errors is very simple, which is to hook the onerror event of the thread instance. This callback function has a parameter error, which has 3 fields: message - error message; filename - the script file where the error occurred; lineno - the line where the error occurred.

Destroy the thread

Inside the thread, use the close method to destroy itself. In the main thread outside the thread, use the terminate method of the thread instance to destroy the thread.
HTML code:

<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>

Script file fibonacci.js code:

//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));
};

Put them in the same directory, run the page file, view the console, you can See the results of the run.
There is another point here. In the main thread, the onmessage event can be hooked in another way:

worker.addEvent
List
ener(&#39;message&#39;, function(event) {
   console.log("Result:" + event.data);
}, false);

Personally, I think it is very troublesome, so it is better to use onmessage directly.

Use other script files

The worker thread can use the global method importScripts to load and use other domain script files or class libraries
. For example, the following are legal usage methods:

importScripts();                        
importScripts(&#39;foo.js&#39;);                
importScripts(&#39;foo.js&#39;, &#39;bar.js&#39;);
After importing, you can directly use the methods in these files. Look at a small example on the Internet:
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); 
 }

Some netizens on the Internet also thought of using the importScripts method here to solve the problem of resource preloading (the browser preloads the resource without parsing and executing the resource). The reason is also Very simple.

Thread nesting

You can also create sub-threads in the working thread, and the various operations are still the same.
Synchronization problem

Worker does not have a lock mechanism, and multi-thread synchronization problems can only be solved by code (such as defining signals variables
).

共享型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。

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

The above is the detailed content of Detailed explanation of Javascript multi-threading in HTML5. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn