Before HTML5, JavaScript runs in browsers worked in a single-threaded way. Although there were many ways to implement multi-thread simulations (such as the setinterval method, setTimeout method, etc. in Javascript), in essence, the program runs is still performed by the JavaScript engine in a single-threaded manner. The worker threads introduced in HTML5 enable the browser-side Javascript engine to execute Javascript code concurrently, thus achieving good support for browser-side multi-threaded programming.
Multithreading in Javascript - WebWorker Web Workers 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. The two types of threads have different uses. Special web workerA 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. The meaning of dedicated is that this thread only processes one requirement at a time. Dedicated threads are implemented in various mainstream browsers except IE and can be used with confidence.
Create threadCreating a worker is simple, just pass the file name of the JavaScript file that needs to be executed in the thread to the constructor.
Thread communicationCommunication between the main thread and the child thread uses the postMessage and onmessage methods of the thread object. No matter who sends data to whom, the sending and sending uses the postMessage method, and the receiver uses the onmessage method to receive data. postMessage has only one parameter, that is, the passed data, and onmessage has only one parameter. Assume it is event, the received data is obtained through event.data.
Send JSON dataJSON is something natively supported by JS. It doesn’t need to be used for nothing. Just use complex data in JSON. For example:
postMessage({'cmd': 'init', 'timestamp': Date.now()});
Handling errorsWhen an error occurs in a thread, its onerror event callback will be called. Therefore, the way to deal with errors is very simple, which is to mount the onerror event of the thread instance. This callback function has a parameter error, which has 3 fields: message - error message; filename - script file where the error occurred; lineno - line where the error occurred.
Destroy threadsInside the thread, use the close method to destroy itself. In the main thread outside the thread, the thread instance's terminate method is used to destroy the thread.
The following is an example to see the basic operation of threads:
HTML code:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>web worker fibonacci</title>
<script type="text/javascript">
onload = function(){
var worker = new Worker('fibonacci.js');
worker.onmessage = function(event) {
console.log("Result:" + event.data);
};
worker.onerror = function(error) {
console.log("Error:" + error.message);
};
worker.postMessage(40);
}
</script>
</head>
<body>
</body>
</html>
Script file fibonacci.js code:
//fibonacci.js
var fibonacci = function(n) {
return n < 2 ? n : arguments.callee(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, and view the console to 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.addEventListener('message', function(event) {
console.log("Result:" + event.data);
}, false);
I personally think it's very troublesome, so why not use onmessage directly.
Use other script filesWorkers can use the global method importScripts to load and use other in-domain script files or class libraries. For example, the following are legal ways to use:
importScripts();/* imports nothing */
importScripts('foo.js'); /* imports just "foo.js" */
importScripts('foo.js', 'bar.js');/* imports two scripts */
After importing, you can directly use the methods in these files. See a small example online:
/**
* Use the importScripts method to introduce external resource scripts, here we use the mathematical formula calculation tool library math_utilities.js
* When the JavaScript engine loads this resource file, continue to execute the following code. At the same time, the following code can be accessed and called
* Variables and methods defined in the resource file.
**/
importScripts('math_utilities.js');
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 divider 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 resources without parsing and executing the resources), and the reason is also very simple.
Thread nestingIn the worker thread, you can also create child threads, and various operations are the same.
Synchronization issuesWorker does not have a lock mechanism, and multithreaded synchronization problems can only be solved by code (such as defining signal variables).
SharedWebWorker Shared web workers are mainly suitable for the problems of multiple connection concurrency. Because it needs to deal with multiple connections, its API is slightly different from dedicated workers. In addition to this, shared web workers, like dedicated workers, cannot access the DOM, and access to form properties is also restricted. Shared web workers cannot cross communications either.Page scripts can communicate with shared web workers, however, slightly different from dedicated web workers (using an implicit port communication) is that communication is explicitly performed by using a port object and attaching a message event handler.
After receiving the first message from the web worker script, the shared web worker attaches an event handler to the activated port. Generally, the handler will run its own postMessage() method to return a message to the calling code, and then the port's start() method generates a valid message process.
Look at the only example you can find on the Internet: create a shared thread to receive instructions sent from different connections, and then implement its own instruction processing logic. After the instruction processing is completed, the result will be returned to each different connected user.
HTML code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Shared worker example: how to use shared worker in HTML5</title>
<script>
var worker = new SharedWorker('sharedworker.js');
var log = document.getElementById('response_from_worker');
worker.port.addEventListener('message', function(e) {
//log the response data in web page
log.textContent =e.data;
}, false);
worker.port.start();
worker.port.postMessage('ping from user web page..');
//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>
</head>
<body onload=''>
<output id='response_from_worker'>
Shared worker example: how to use shared worker in HTML5
</output>
send instructions to shared worker:
<input type="text" autofocus oninput="postMessageToSharedWorker(this);return false;">
</input>
</body>
</html>
Script file code:
// Create a shared thread to receive instructions sent from different connections. After the instruction processing is completed, the result will be returned to each different connected user.
var connect_number = 0;
onconnect = function(e) {
connect_number =connect_number+ 1;
//get the first port here
var port = e.ports[0];
port.postMessage('A new connection! The current connection number is '
+ connect_number);
port.onmessage = function(e) {
//get instructions from requester
var instruction=e.data.instruction;
var results=execute_instruction(instruction);
port.postMessage('Request: '+instruction+' Response '+results
+' from shared worker...');
};
};
/*
* this function will be used to execute the instructions send from requester
* @param instruction
* @return
*/
function execute_instruction(instruction)
{
var result_value;
//implement your logic here
//execute the instruction...
return result_value;
}
In the above shared thread example, a shared thread object is constructed on the main page, that is, each user connection page, and a method is defined to send the incoming user instructions to the shared thread. At the same time, connect_number is defined in the implementation code snippet of the shared thread to record the total number of connected to the shared thread. After that, use the onconnect event processor to accept connections from different users and parse the instructions they pass. Finally, a method execute_instruction is defined to execute the user's instructions. After the instruction execution is completed, the result will be returned to each user.
Here we did not use the onmessage event handler of the worker thread like the previous example, but used another method to addEventListener. In fact, as mentioned earlier, the implementation principles of these two are basically the same, but there are some slight differences here. If you use addEventListener to accept messages from shared threads, you must first use the worker.port.start() method to start this port. After that, you can receive and send messages normally just like the way a worker thread is used.
Final statement Things you can do in a thread :1. Can use setTimeout(), clearTimeout(), setInterval(), clearInterval() and other functions.
2. Can use navigator objects.
3. Can use XMLHttpRequest to send requests.
4. You can use Web Storage in the thread.
5. You can use self to get the scope of this thread in the thread.
Things that cannot be done in threads :1. DoM/BOM objects other than navigator cannot be used in threads, such as window and document (if you want to operate, you can only send messages to the worker creator and operate through callback functions).
2. Variables and functions in the main thread cannot be used in the thread.
3. Operation commands with suspend effects cannot be used in threads, such as alert, etc.
4. JS cannot be loaded across domains in threads.
Threads also require resource consumption, and using threads will also bring some complexity, so if there is no sufficient reason to use additional threads, then don't use them.
Practical referenceOfficial document: http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html
WebWorker classification description: http://www.w3schools.com/html5/html5_webworkers.asp
Template worries: http://www.CuoXIn.com/w3school/html5/
WebWorker Overview: https://developer.mozilla.org/en/Using_web_workers