What is webWorker?

As we all know, JavaScript is single-threaded and can only handle one task at a time, and we simulate “parallelism” with techniques like setTimeout(), setInterval(), Ajax, and event handlers. But they’re not really parallel:

Web Worker is 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.

This takes advantage in large part of today’s ever-increasing computing power to be able to process two tasks in parallel at the same time.

Swimming, fitness learn about: blog, front-end accumulation document, public account, GitHub

scenario

When we have tasks that take a lot of time and perform complex calculations, the page gets stuck: it takes a long time for the user to click on the page to respond because the previous task has not been completed and the next task has to wait in line. This is a terrible experience for users, and web workers are designed to solve complex computing that takes a lot of time!

What WebWorker does: Create worker threads

WebWorker allows a worker thread to be created in addition to the main thread. While the main thread is executing tasks, the worker thread can also execute its own tasks in the background without interfering with each other.

In this way, JS becomes a multi-threaded environment. We can assign high-latency and time-consuming operations to worker threads, and finally return the results to the main thread. Because the time-consuming tasks are undertaken by the Web worker, the main thread will be very smooth!


The main thread

Let’s start with chestnuts:

Codepen, I’ve written a class here, and I have a detailed comment on it, so you can refer to it.

Create the worker object:

The main thread calls the new Worker() constructor to create a new Worker thread. The constructor argument is a URL. There are two ways to generate this URL:

  1. Script file:

    const worker = new Worker('https://~.js');
    Copy the code

    Because of the worker’s two limitations:

    1. The script file assigned to the Worker thread must be the same as the script file on the main thread.

    2. The worker cannot read local files (cannot open the local file system file://). The script it loads must come from the network.

    As you can see, there are a lot of restrictions, so if you want to use this form, it is recommended to put the files in a static folder in your project, and copy them in when you package them, so that you can get the fixed links.

  2. String form:

    const data = '// Worker thread do something';
    // Convert to binary objects
    const blob = new Blob([data]);
    / / generated url
    const url = window.URL.createObjectURL(blob);
    / / load the url
    const worker = new Worker(url);
    Copy the code

    This is what we use in chestnuts, so we can show you.

    In the project: we can write the worker thread logic in THE JS file, and then string, and then export, import, with WebPack modular management, so that it is easy to use.

Other apis for the main thread:

1. Communication between main thread and worker thread:

worker.postMessage({
  hello: ['hello'.'world']});Copy the code

They can communicate with each other by passing objects and arrays, so that we can do things based on the information that we’re passing to each other, like we can set a type attribute, what function to execute when it’s hello, what function to execute when it’s world.

It is worth noting that they communicate with each other by passing data in the form of copies, which need to be serialized and then deserialized at the other end. This means:

  1. We can’t pass data that can’t be serialized, such as a function, it will throw an error.
  2. Changing data on one end does not affect the other end, because the data is not referenced, it is copied.

2. Listen for the information returned by the worker thread

worker.onmessage = function (e) {
    console.log('Data received by parent process:', e.data);
    // doSomething();
}
Copy the code

3. The main thread closes the worker thread

Once the Worker thread is successfully created, it will always run, which is conducive to responding to the communication of the main thread at any time.

This is why the Worker consumes more computing resources (CPU) on the computer, and should be closed once it is used up.

worker.terminate(); // The main thread closes the worker thread
Copy the code

4. Listening error

// The worker thread reported an error
worker.onerror = e= > {
    // e.filename - File name of the script where the error occurred; E. lineno - Error line number; And E.message - a readable error message
    console.log('onerror', e);
};
Copy the code

You can also write the two errors together like I did with the chestnuts, and if there is an error, you can send the information out.


Worker thread

Self represents the worker process itself

The execution context of the worker thread is something called WorkerGlobalScope, which is different from the context of the main thread (window).

We can use self/WorkerGlobalScope to access global objects.

Listen for information from the main thread:

self.onmessage = e= > {
    console.log('Message from main thread:', e.data);
    // do something
};
Copy the code

Send information to the main thread

self.postMessage({
    hello: [ 'This message'.'From worker thread']});Copy the code

The worker thread closes itself

self.close()
Copy the code

Worker thread loads script:

Worker threads can import scripts by accessing a global function, imprtScripts(), that takes zero or more URIs as arguments.

importScripts('http~.js'.'http~2.js');
Copy the code
  1. All global variables in the script can be used by the worker thread.

  2. Scripts are downloaded in a fluid order, but are executed in the order of the file names passed in importScripts(), and the process is synchronous.

Worker thread limit

Because the worker creates another thread that is not on the main thread, there are some corresponding restrictions, we cannot use the following objects:

  1. The window object
  2. The document object
  3. DOM object
  4. The parent object

We can use the following objects/functions:

  1. Browser: Navigator object

  2. URL: Location object, read-only

  3. Send the request: XMLHttpRequest object

  4. Timer: setTimeout/setInterval, also great for polling worker threads!

  5. Application Cache: Application Cache


Multiple worker threads

  1. Multiple worker threads can be created within the main thread

    At the bottom of the chestnut.

  2. Worker threads can also be created within worker threads, using same-origin script files to create.

    In a worker thread and then a new worker thread will not be able to use the window. The URL. CreateObjectURL (blob), you need to use the homologous script file to create a new worker thread, because we can’t access to the window object.

    Here is not convenient to demonstrate, following the main thread to create worker threads is a routine, but changed to script file form to create worker threads.

Transfer binary data between threads

Since the communication between the main thread and the worker thread is a copy relationship, when we want to pass a huge binary file to the worker thread for processing (which is what the worker thread is used to do), it will undoubtedly cause performance problems to pass the data in the way of copy.

Fortunately, Web Worker provides a way to transfer data, allowing the main thread to transfer binary data directly to child threads. This approach offers a huge performance improvement over the original copy approach.

Once the data is transferred to another thread, the original thread will no longer be able to use the binary data, in order to prevent the cumbersome situation of multiple threads modifying the data at the same time

The following chestnut comes from a brief talk about HTML5 Web workers

// Create binary data
var uInt8Array = new Uint8Array(1024*1024*32); // 32MB
for (var i = 0; i < uInt8Array .length; ++i) {
    uInt8Array[i] = i;
}
console.log(uInt8Array.length); // The length before transmission is 33554432
// Create the worker thread as a string
var myTask = ` onmessage = function (e) { var data = e.data; console.log('worker:', data); }; `;

var blob = new Blob([myTask]);
var myWorker = new Worker(window.URL.createObjectURL(blob));

// Use this format (a,[a]) to transfer binary data
myWorker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]); // Send data, transfer data

console.log(uInt8Array.length); // The thread has a length of 0
Copy the code

Binary data can be: File, Blob, ArrayBuffer and other types. It can also be sent between worker threads, which is very convenient for image processing, sound processing, 3D computing and so on, without incurring performance burden

Application scenario:

  1. Mathematical operations

  2. Image, video and other file processing

  3. Bulk data retrieval

    For example, when the user input, we retrieve the answer in the background, or help the user association, error correction and other operations.

  4. Time-consuming tasks are thrown into the Webworker to free up our main thread.

Compatible with:

No specific date was found, one blog was written in July, 10 years ago, which means web Worker has been around for at least 8 years. The following compatibility is from MDN:

Chrome: 4, Firefox: 3.5, Internet Explorer: 10.0, Opera: 10.6, Safari: 4

Now compatibility is better, if you really don’t trust:

if (window.Worker) {
    ...
}else{... }Copy the code

Conclusion:

The emergence of Web Worker brings background computing capability to the browser and allocates time-consuming tasks to Worker threads, which to a large extent alleviates the blocking problem of UI rendering on the main thread and improves page performance.

It is not complicated to use. If there are complex problems in the future, remember to throw them to the web worker in the background of our browser to deal with

After reading, must study a below in chestnut, oneself tinker, practice out true knowledge!

PS: I wrote last month about how to use WebSocket. If you are interested, you can check it out.

I hope that after watching the friends can click like/follow, your support is the biggest encouragement to me.

Blog, front end accumulate document, public account, GitHub

The above 2018.11.25

References:

MDN

Web Worker use tutorial

Talking about HTML5 Web Worker