Let’s look at a couple of examples

This example is done by showing the earth’s seismic zones through red dots, The data is taken from the Geological Survey through console.log to see how long it takes to calculate the data. No Webworker No Web workers – all on main thread Use One webworker Two Web workers Use Eight Eight Web workers use 20 20 Web workers

Verdict: Yes? // Keep thinking

background

JavaScriptThe engine runs single-threaded,JavaScriptIn the time consumingI/OOperations are handled as asynchronous operations, including keyboard and mouse operationsI/OInput and output events, window sizeresizeEvents, timers (SetTimeout and setInterval) events,AjaxRequest networkI/OThe callback, and so on. When these asynchronous tasks occur, they will be placed in the browser’s event task queue, untilJavaScriptThe run-time execution is executed on a first-in-first-out basis only when the execution thread is idle, but it is still single-threaded.

Although JS runs in a browser, it is single-threaded, one JS thread per window, but browsers are not single-threaded, such as Webkit or Gecko engines, may have the following threads:



Javascript engine threadsInterface render thread Browser events trigger thread Http request threadCopy the code

Many people think that async (promise async/await) is sufficient for ordinary work through similar event loops. However, if complex operations are performed, the deficiencies of these asynchronous pseudo-threads will gradually be shown. For example, setTimeout gets incorrect values. In addition, if the page has complex computation, it is easy to trigger the suspended animation state. In order to have multithreading function, Webworker was born. However, this does not mean that the JavaScript language itself supports multithreading. For the JavaScript language itself, it still runs on a single thread. Web Worker is just a capability/API provided by the browser (host environment).

Introduction to the

Web workers are part of the HTML5 standard, which defines a set of apis that allow a JavaScript program to run in a thread other than the main thread. Worker thread allows developers to write background programs that can run for a long time without being interrupted by users to execute transactions or logic, and at the same time ensure timely response of the page to users. Some large amounts of calculating code can be handed over to The Web worker to run without freezing the user interface. Cases will be introduced later

type

Web workers can be divided into two types: dedicated thread Dedicated Web worker and shared thread shared Web worker. The Dedicated Web worker ends when the current page closes; This means that a Dedicated Web worker can only be accessed by the page that created it. The corresponding Shared Web worker can be accessed by multiple pages. In Javascript code, the “Work” type represents a Dedicated Web worker, while the “SharedWorker” type represents a Shared Web worker. Shared workers can be Shared by multiple pages (in the same domain)

How to create

Web workers are created in the main thread by passing in the URL of the file. As follows:



let webworker = new Worker('myworker.js');Copy the code

The webworker instance object is returned, which acts as a bridge between the main thread and other threads



onmessage:Listen for an eventpostmessage:Send eventCopy the code

The relevant API for communication case code is as follows



// main thread main.js
var worker = new Worker("worker.js");
worker.onmessage = function(event){
    The main thread receives a message from the child thread
};
// The main thread sends messages to child threads
worker.postMessage({
    type: "start",
    value: 12345
});

//web worker.js
onmessage = function(event){
   / / received
};
postMessage({
    type: "debug",
    message: "Starting processing..."
});Copy the code

The demo

How to terminate

If at some point we do not want the Worker to continue running, we need to terminate the thread by calling terminate on the main thread of the Worker or close on the corresponding thread:



// mode one main.js stops in the main thread
var worker = new Worker('./worker.js');
.
worker.terminate();

// Worker.js
self.close()Copy the code

The error mechanism

The onError API is provided



worker.addEventListener('error'.function (e) {
  console.log('MAIN: '.'ERROR', e);
  console.log('filename:' + e.filename + '-message:' + e.message + '-lineno:' + e.lineno);
});

// event.filename: the name of the Worker script that caused the error;
// event.message: error message;
// event.lineno: error line number;Copy the code

sharedWorker

For Web workers, a TAB page can only correspond to one Worker thread, which is independent of each other. And SharedWorker provides the ability to let pages in different tags share the same Worker script thread; And, of course, one important constraint is that they have to satisfy the same origin policy, that is, they have to be in the same domain; Instantiate Worker threads in pages (multiple) :



// main.js

var myWorker = new SharedWorker("worker.js");

myWorker.port.start();

myWorker.port.postMessage("hello, I'm main");

myWorker.port.onmessage = function(e) {
  console.log('Message received from worker');
}Copy the code


// worker.js
onconnect = function(e) {
  var port = e.ports[0];

  port.addEventListener('message'.function(e) {
    var workerResult = 'Result: ' + (e.data[0]);
    port.postMessage(workerResult);
  });
  port.start();
}Copy the code

The online demo

Father and son thread

Create a thread within a thread

Context and scope

There is no window global object in the running environment of Worker threads, nor can they access DOM objects, so generally they can only perform pure JavaScript computations. However, he can still get the API provided by some browsers:

SetTimeout (), clearTimeout(), setInterval(), clearInterval() : With a function designed, the Worker can be created again in Worker: thread; XMLHttpRequest: object: means we can execute ajax requests in Worker threads; Navigator object: ppName, appVersion, Platform, userAgent and other information can be obtained; Location object (read only) : Gets information about the current URL; Application Cache indexedDB WebSocket, Promise,

Libraries or external scripts are introduced and accessed

In threads, the importScripts method is provided. If importScripts is used in a thread, follow these steps to resolve it



1Parse each parameter of the importScripts method.2If there are any failures or errors, throw a SYNTAX_ERR exception.3, try to get the script resource from the URL resource location provided by the user.4For each parameter of the importScripts method, obtain script resources in the order provided by the user and proceed with other operations.Copy the code


// worker.js
importScripts('math_utilities.js'); 
onmessage = function (event) 
 { 
     var first=event.data.first; 
     var second=event.data.second; 
     calculate(first,second); Calculate is a method in math_utilities.js
 }; 
Copy the code

You can also introduce more than one at a time



// Can pass more than one time
importScripts('script1.js'.'script2.js');Copy the code

XMLHttpRequest



onmessage = function(evt){
    var xhr = new XMLHttpRequest();
    xhr.open("GET"."serviceUrl"); Xhr.onload = function(){postMessage(xhr.responsetext); }; xhr.send(); }Copy the code
jsonp


/ / set the json
function MakeServerRequest(a) 
{
    importScripts("http://SomeServer.com?jsonp=HandleRequest");
} 

/ / the json callback
function HandleRequest(objJSON) 
{
    postMessage("Data returned from the server... FirstName: " 
                  + objJSON.FirstName + " LastName: " + objJSON.LastName);
} 

// Trigger the server request for the JSONP data 
MakeServerRequest();Copy the code

Communication principle

Communication from one thread to another is actually a process of value copying, which is actually json.stringify followed by json.parse. Binary data, such as files, BLObs, and arrayBuffers, can also be exchanged between the main thread and child threads, and can also be sent between threads. However, sending binary data as a copy can cause performance problems. For example, if the main thread sends a 50MB file to the child thread, by default the browser will generate a copy of the original file. To solve this problem, JavaScript allows the main thread to transfer binary data directly to the child thread, after which the main thread can no longer use the data. This is to prevent multiple threads from modifying data simultaneously. This method of transferring data is called Transferable Objects. However, many browsers now support Transferable Objects, a zero-copy transfer technology that can greatly improve performance by specifying that all data transferred is zero-copy



var abBuffer = new ArrayBuffer(32);
aDedicatedWorker.postMessage(abBuffer, [abBuffer]);Copy the code

You can also specify one to use zero copy



var objData = {
   "employeeId": 103."name": "Sam Smith"."dateHired": new Date(2006.11.15),
   "abBuffer": new ArrayBuffer(32)}; aDedicatedWorker.postMessage(objData, [objData.abBuffer]);Copy the code

Worker thread life cycle

Communication between worker threads must depend on the browser context and pass messages through their MessagePort object instances. The global scope of each worker thread has a list of ports for those threads, including MessagePort objects used by all threads. In the case of dedicated threads, the list also contains an implicit MessagePort object. The global scope object WorkerGlobalScope for each worker thread also has a list of worker threads, which is empty at initialization. They are populated when a worker thread is created or has a parent worker thread. Finally, the global scoped object WorkerGlobalScope for each worker thread also has the document model for that thread, which is empty at initialization. When a worker thread is created, the document object is populated. Whenever a document object is discarded, it is removed from the document object enumeration.

The performance test

Initialization test


// Some machines webwoker initialization time Macbook Pro:2 workers, 0.4 milliseconds on average
Macbook Pro: 4 workers, 0.6 milliseconds on average
Nexus 5: 2 workers, 6 milliseconds on average
Nexus 5: 4 workers, 15 milliseconds on average (border-line UI jank)
Copy the code
Transmission speed test

1. Common JSON /object

2, tranferable objects



Transferable visible objectsThe transmission speed is much higher

Typical application scenarios are as follows

1) The simplest application of Web Worker is to do background calculation, which does not interrupt operations of foreground users. 2) Image processing by using data obtained from

or

limit

1. Read-only access to Location and Navigator that cannot access DOM and BOM objects, and navigator encapsulates as WorkerNavigator object, changing some properties. The local file system cannot be read. 2. The child thread communicates with the parent thread through value copy. The modification of the child thread to the communication content does not affect the main thread. 3, Not really multithreading, multithreading because of the browser function 4, compatibility 5 because threads import external JS through importScripts and execute directly, 6. Limit the number of webworker threads that can be created by most browsers. Although you can expand it manually, if you do not set it, it is basically within 20 threads, each thread is about 5M. You need to manually shut down some unused threads in order to create new threads (related solutions)

Js multithreaded library

1, tagg2

[1] www.html5rocks.com/zh… [2] www.alloyteam.com/2015… [3] typedarray.org/concur… [4] www.andygup.net/advanc… [5] developer.mozilla.org… [6] coolaj86.github.io/htm… [7] www.xyhtml5.com/webwor…