Recently, I encountered some performance problems in the project. In order to prevent the experience from being affected by the loading of pictures one by one and to improve efficiency, data and a large number of pictures needed to be loaded in advance constantly. At that time, we used worker to optimize the performance in the project, and put the large amount of computation and the pre-loading of pictures into worker for operation.

What is a worker

Using A Web Worker, we can run Javascript in the background of the browser without using the browser’s own threads. Web Workers can improve the overall performance of an application and improve the user experience. If you are not familiar with workers, please refer to it. This article will mainly introduce the application scenarios and performance issues of workers.

How to use Worker to preload images

Image preloading problem analysis

  • Generally, workers are not used to preload images in projects, but how to realize lazy loading of images. However, based on business needs, workers are used to preload images. You may not need the preloaded images, but this article should help you understand workers a lot;
  • We have many options for loading images (not all, if you have other options you’d like to share) :
    • The image is loaded by manipulating the Img tag in the DOM.
    • It can also be loaded via the JS Image object.
    • You can also load through Ajax.
  • Loading images by constantly manipulating the DOM is the most resource-intensive and the slowest solution. Loading with an Image object is memory intensive and consumes resources on the main thread; It is most appropriate to load the Image in the worker, but the child thread cannot manipulate the DOM, so the Image object cannot be used, so we can only consider using Ajax to implement the Image. Fortunately, there is no cross-domain problem with either solution to load the Image.

The specific application

Start a single worker to load the image, and postMessage the data back to the worker every time. No more nonsense, directly paste the code:

  • Enable the worker in index. js
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)
    */
    console.log(event.data);
 };

 w.onerror = function(e){
     e.currentTarget.terminate();
    console.log('erro: ' + e.message);
};Copy the code
  • The image is requested in worker.js
letArr = [...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

Summary is important

  • Comparing the performance of using XMLHttpRequest in the worker and using XMLHttpRequest in the main thread, I used Node to crawl over 500 image urls of a website to test the following conclusions:
    • Each XMLHttpRequest request in the main thread consumes resources. Although the browser opens another thread during the request, it consumes resources in the main thread during the interaction. While using worker does not occupy the main thread too much, it only consumes resources when starting worker process.
    • When there is a large number of XMLHttpRequest requests, when the network speed is slow, the worker using XMLHttpRequest and using XMLHttpRequest on the main thread will not feel the block, when the network speed is very fast, a large number of requests will be returned.
  • In the process of using the worker, if the actual reference of the worker is 0, the worker will be shut down immediately after it is idle. If the worker’s actual reference is not 0, the worker is idle and will not be shut down.