1 the introduction

This week’s intensive reading article is speedy Introduction-to-Web-workers, which is a quick introduction to Web workers. Take the opportunity of intensive reading to talk about the understanding and application of Web workers.

2 an overview

It’s like a division of labor, where you do the coding and your friend does the designing, so you can focus on doing your job and get it done faster.

This paper describes two characteristics of Web Workers through an analogy:

  1. Efficient.
  2. In parallel.

Because browsers are single-threaded, any large, time-consuming JS task will jam the interface and render the browser unable to respond to any action, which makes the user experience very bad. Web Workers can disassemble time-consuming tasks to reduce the main thread pressure and avoid the main thread being unresponsive.

However, CPU resources are limited, so Web Workers cannot increase the overall operating efficiency. Considering the loss of communication, the overall computing efficiency will decrease to some extent.

Create Web Workers

const worker = new Worker(".. /src/worker.js");
Copy the code

In the above code, worker is a Web Workers instance, and the code executed is.. / SRC /worker.js file.

To send and receive messages

Web Workers are used to execute the asynchronous script, and once they know how it communicates with the main thread, they can run the asynchronous script at the specified time and pass the results to the main thread when they are finished.

The main thread receives and sends Web Workers messages

const worker = new Worker(".. /src/worker.js");

worker.onmessage = e= > {};

worker.postMessage("Marco!");
Copy the code

Each worker instance receives messages via onMessage and sends messages via postMessage.

Web Workers Sends and receives main thread messages

self.onmessage = e= > {};

self.postMessage("Marco!");
Copy the code

Similar to the main thread code, in the Web Workers code, the onMessage receives the message from the master thread or other Workers. Messages can also be sent via postMessage.

Destruction of Web Workers

worker.terminate();
Copy the code

The content of the article is so much, is there to write too simple! The author combines own use experience, supplement a few knowledge again.

3 intensive reading

Transferable Objects

Object migration is the transfer of object references to the context of Web Workers at no cost, without the need for structural copy.

What should be explained here is that the communication between the main thread and Web Workers is not the transfer of object reference, but the process of serialization/deserialization. When the object is very large, the serialization and deserialization will consume a lot of computing resources and reduce the running speed.

The above figure fully demonstrates that large object transfer, using object transfer, is better than structural copy.

Object transfer is a simple way to pass the object reference to postMessage by adding an argument:

var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);
Copy the code

Browser compatibility is also good: Currently Chrome 17+, Firefox, Opera, Safari, IE10+. Transferable Objects: Lightning Fast! .

It should be noted that after the object reference is transferred, the original context cannot access the object, and the main thread can normally access the object after Web Workers restore the object to the main thread context again.

How to create Web Workers without JS files

Web Workers have such great advantages, but it is really inconvenient to create a JS file in the same domain, especially in the front and back end separation of the team is more thorough, the front-end team can control only a JS file. Here are some ways to create Web Workers without using JS files:

Webpack plugin – worker-loader

Worker-loader is a Webpack plug-in that can extract all the dependencies of an ordinary JS file, package and replace the invocation, and inline the source code in Blob form.

import Worker from "worker-loader! ./file.worker.js";

const worker = new Worker();
Copy the code

The magic of the above code is to convert it to the following execution:

const blob = new Blob([codeFromFileWorker], { type: "application/javascript" });
const worker = new Worker(URL.createObjectURL(blob));
Copy the code

Blob URL

The second approach follows naturally from the first: if you don’t want to use the Webpack plugin, you can create your own Blob:

const code = ` importScripts('https://xxx.com/xxx.js'); self.onmessage = e => {}; `;

const blob = new Blob([code], { type: "application/javascript" });
const worker = new Worker(URL.createObjectURL(blob));
Copy the code

The code looks lighter, but the problem is that when you encounter complex dependencies, you can’t access packages in the main thread environment without having to convert them all to scripts referenced by importScripts. If you do run into this problem, you can solve it with the first Webpack plug-in, which automatically packages all of the file’s dependencies into source code.

Manage the postMessage queue

Why is postMessage queued, and why should it be managed?

First of all, it is necessary to make a queue in the architecture design of Web Workers, because when calling postMessage, the corresponding Web Workers may not have completed the initialization, so the bottom layer of the browser must manage a queue, and consume successively when the Initialization of Web Workers is completed. This ensures that any postMessage sent is received by Web Workers at any time.

Second, the reasons why this queue should be maintained manually may depend on the following:

  • Business reasons, up frontpostMessageBefore consumption, do not send new messages or discard new messages. At this time, we need to get the execution result receipt of Web Workers through two-way communication and manually control the queue.
  • For performance reasons, Web Workers are usually used to perform time-consuming synchronization operations. If the operation takes a long time, it does not make sense to fill multiple message queues in a short time.

As shown in the figure above, SQL Parser, which needs to be processed every time the user inputs, is time-consuming and timely placed in Web Workers may also cause Workers to burst to no response, which requires not only the use of multiple Workers buffer pools, but also the filtering of execution queues. The user only cares about the result of the last Parser input.

When the Web Workers calculation is stuck, there is no other way but to destroy the Worker, and the cost of destroying the Worker is relatively high, so it cannot destroy every user input and create Web Workers. Therefore, the Workers buffer pool is used. When the buffer pool is full, When a new consumption queue comes in, the entire Workers buffer pool can be destroyed and a new batch of buffer pools can be used to consume user input again.

4 summarizes

Web Workers is a good helper to dismantle asynchronous computing. Vscode Web version also completes code prompt and highlighting asynchronously through Web Workers. The author has made a comparison and found that the performance of Web Workers is significantly improved.

Manage your Web Workers message queues to prevent Web Workers from becoming unresponsive due to synchronous computations! Build an intelligent message queue and design the best queue consumption model for your business needs.

5 More Discussions

The discussion address is: Intensive reading about Web Workers · Issue #108 · dT-fe /weekly

If you’d like to participate in the discussion, pleaseClick here to, with a new theme every week, released on weekends or Mondays. Front end Intensive Reading – Helps you filter the right content.