(Add star to front end to improve front end skills)

Author: Front End Afternoon Tea official number/SHERlocked93

In the past, we always said that JS is a single thread without multi-thread. When JS runs a long time synchronous task in the page, it will lead to page suspension and affect the user experience, so it is necessary to set the task in the task queue. The tasks in the task queue are not multithreaded. However, now HTML5 provides us with the ability of front-end development – Web Workers API. Let’s take a look at what Web Worker is, how to use it and how to use it to produce in actual production.

1. An overview of the

Web Workers enables a Web application to run a script operation in a background thread separate from the main execution thread. This has the advantage of being able to perform time-consuming processing tasks in a separate thread, allowing the main (usually UI) thread to run without blocking.

Its function is to create a multi-threaded running environment for JS, allowing the main thread to create worker threads and assign tasks to the latter. When the main thread is running, worker threads are also running without interfering with each other, and the results are returned to the main thread after the running of worker threads. The advantage of this is that the main thread can delegate computationally intensive or high-latency tasks to the worker thread so that the main thread is relaxed and not blocked or slowed down. This does not mean that the JS language itself supports multi-threading capabilities, but rather that the browser as the host environment provides A multi-threaded environment for JS to run.

However, once a worker is created, it will run all the time and will not be interrupted by the activities of the main thread, which is conducive to responding to the connectivity of the main thread at any time, but also causes a waste of resources, so it should not be overused and should be closed after use. In other words: If the worker has no instance reference, the worker will be shut down as soon as it is idle; If the worker column reference is not 0, the worker is idle and will not be closed.

Take a look at the compatibility

2. Use

2.1 limit

There are a few caveats to the use of worker threads

  1. The same origin limits the script files executed by worker threads must be the same origin as the main thread script files, which is of course true. Worker threads should not be allowed to read files on other machines

  2. File limitation For safety, the worker thread cannot read local files, and the scripts it loads must come from the network and be of the same origin as the script of the main thread

  3. DOM operations restrict worker threads to run in a different global context from the main thread’s window, where they cannot read the DOM object of the page where the main thread is located, nor can they obtain objects such as Document and window. However, you can get navigator, Location (read only), XMLHttpRequest, setTimeout family, and other browser apis.

  4. Communication restriction Worker thread and main thread are not in the same context and cannot communicate directly. They need to communicate through postMessage method.

  5. The script restricts worker threads from executing alert and confirm, but can make Ajax requests using the XMLHttpRequest object.

2.2 example

Generating Worker threads in the main thread is easy:


     

    var myWorker = new Worker(jsUrl, options)

Copy the code

The Worker() constructor, whose first argument is the url of the script (must comply with the same origin policy), is required and can only load JS scripts, otherwise an error is reported. The second parameter is the configuration object, which is optional. One of its functions is to specify the name of the Worker to distinguish between multiple Worker threads.

                                
     

    / / main thread

    var myWorker = new Worker ('worker.js' , { name : 'myWorker' });

    / / Worker thread

    self.name // myWorker

Copy the code

Worker thread js file:


     

    // workerThread1.js

    let i = 1

    function simpleCount() {

    i++

    self.postMessage(i)

    setTimeout(simpleCount, 1000)

    }

    simpleCount()

    self.onmessage = ev => {

    PostMessage (ev.data + 'hehe ~')

    }

Copy the code

In the body of the HTML file:


     

    <! -- Main thread, body tag of HTML file -->

    <div>

    <span id='app'></span>

    <input type='text' title='' id='msg'>

    <button onclick='sendMessage()'>

    <button onclick='stopWorker()'>stop! </button>

    </div>

    <script type='text/javascript'>

    If (typeof(Worker) === 'undefined') // Check whether the browser supports Worker before using Worker

    document.writeln(' Sorry! No Web Worker support.. ')

    else {

    window.w = new Worker('workerThread1.js')

    window.w.onmessage = ev => {

    document.getElementById('app').innerHTML = ev.data

    }

    window.w.onerror = err => {

    w.terminate()

    Console. log(error.filename, error.lineno, error.message) // the filename, line number, and content of the error occurred

    }

    function sendMessage() {

    const msg = document.getElementById('msg')

    window.w.postMessage(msg.value)

    }

    function stopWorker() {

    window.w.terminate()

    }

    }

    </script>

Copy the code

You can run it yourself to see the effect, using some common apis

The API in the main thread, worker, is an instance of worker:

  • Worker.postmessage: The main thread sends a message to the worker thread. The message can be any type of data, including binary data

  • Worker. terminate: The main thread closes the worker thread

  • Worker. onMessage: Specifies the callback to which the worker thread sends a message, also via worker.addEventListener(‘message’,cb)

  • Worker.onerror: specifies a callback to the worker thread when an error occurs, also worker.addeventListener (‘error’,cb)

The global object in the Worker thread is self, which represents the child thread itself. In this case, this refers to self, on which there are some apis:

  • Self. PostMessage: The worker thread sends a message to the main thread, which can be any type of data, including binary data

  • Self. close: The worker thread closes itself

  • Self. onMessage: Specifies the callback to which the main thread sends a worker thread message, or self.addeventListener (‘message’,cb)

  • Self.onerror: Specifies the callback to the worker thread when an error occurs, or self.addeventListener (‘error’,cb)

Note that the w.postMessage(aMessage,transferList) method accepts two parameters. AMessage can transfer any type of data, including objects. This communication is a copy relationship, that is, value transfer rather than address transfer. It doesn’t affect the main thread. In fact, the internal operation mechanism of the browser is to serialize the communication content first, and then send the serialized string to the Worker, who then restores it. An array of optional Transferable objects used to transfer ownership. If ownership of an object is transferred, it becomes unavailable (aborted) in the context in which it was sent, and only available in the worker to which it was sent. Transferable objects are instance objects such as ArrayBuffer, MessagePort, or ImageBitmap. Null cannot be passed into the transferList array.

See MDN-WorkerglobalScope for a more detailed API.

API for loading scripts in worker threads:


     

    ImportScripts ('script1.js') // Loads a single script

    ImportScripts ('script1.js', 'script2.js') // Loads multiple scripts

Copy the code

3. Actual combat scenarios

In my opinion, Web workers can be used as calculators. Take them out and press them when you need them and put them away when you don’t need them

  1. Encrypt the data

    Some encryption and decryption algorithms are complicated, or when a lot of data is encrypted and decrypted, it will consume very much computing resources, resulting in no response from THE UI thread. Therefore, it is a good time to use Web Worker threads, which can enable users to operate THE UI more seamlessly.

  2. Prefetching data

    Sometimes, to speed up data loading, you can use the Worker thread to fetch data ahead of time because the Worker thread can use XMLHttpRequest.

  3. pre-rendered

    In some rendering scenes, such as rendering complex canvas, effects such as reflection, refraction, light and shadow, materials, etc. need to be calculated. The logic of these calculations can be executed by Worker threads or multiple Worker threads. Here is an example of ray tracing.

  4. Complex data processing scenarios

    Some retrieval, sorting, filtering, and analysis can be very time consuming and can be done using the Web Worker without using the main thread.

  5. Preloading images

    Sometimes a page has a lot of images or several large images. If business constraints do not allow lazy loading, you can also use the Web Worker to load images. You can refer to the exploration in this article, which is briefly summarized here.


     

    / / main thread

    let w = new Worker("js/workers.js");

    w.onmessage = function (event) {

    var img = document.createElement("img");

    img.src = window.URL.createObjectURL(event.data);

    document.querySelector('#result').appendChild(img)

    }

    / / worker thread

    Let arr = [... many image path];

    for (let i = 0, len = arr.length; i < len; i++) {

    let req = new XMLHttpRequest();

    req.open('GET', arr[i], true);

    req.responseType = "blob";

    req.setRequestHeader("client_type", "DESKTOP_WEB");

    req.onreadystatechange = () => {

    if (req.readyState == 4) {

    postMessage(req.response);

    }

    }

    req.send(null);

    }

Copy the code

Attention should be paid to the actual Web Workers:

  1. Although using the worker thread does not occupy the main thread, starting the worker can be resource consuming

  2. Using XMLHttpRequest in the main thread The browser opens an asynchronous HTTP request thread during the request, but the interaction still consumes the main thread resources

How to use Web workers in ES6+Webpack

As for Shared workers, Service workers, etc., we won’t watch it. IE doesn’t like it


Online posts are mostly different in depth, even some inconsistent, the following article is a summary of the learning process, if you find mistakes, welcome to comment out ~

Reference:

  1. MDN – Web Workers concept and usage

  2. Ruan Yifeng – How to use Web Worker

  3. How JavaScript works -Web Workers classification and 5 usage scenarios

  4. Great use of Web workers in projects

  5. How to use Web Workers in ES6+Webpack

Recommended reading

(Click on the title to jump to read)

How does Ming become a front-end engineer?

Create a very simple offline page using the Service worker

Find this article helpful? Please share it with more people

Pay attention to “front-end daqo” plus star label, improve front-end skills

Good article, I’m reading ❤️