Web workers and its API: Run intensive tasks in the background


Reading time: 30 minutes

JavaScript was usually designed to run in a single-threaded environment (multiple scripts cannot run at the same time).
Consider a situation where we need to handle UI events, query and process large amounts of API data, and manipulate the DOM. JavaScript will hang the browser in situation where CPU utilization is high.
In some situations where javascript has to run big loops, the browser may prompt error messages like the image below.
error
The situation explained above can be handled using Web Workers, who will do all the computationally expensive tasks without interrupting the user interface and typically run on separate threads.

👉 Note: When a script is executing inside a Web Worker, it cannot access the webpage's window object (window.document), which means that Web Workers don't have direct access to the web page and the DOM API. Although Web Workers cannot block the browser's user interface, they can still consume CPU cycles and make the system less responsive.

How Web Workers Work?

Web Workers are initialized with the URL of a JavaScript file, which contains the code the worker will execute. This code sets event listeners and communicates with the script that spawned it from the main page.

Syntax:

var worker = new Worker('process.js');

The browser will asynchronously download the js script file and execute it. If any wrong path is given, then it will fail silently.
Once the Web Worker is spawned, communication between web worker and its parent page is done using the postMessage() method. Depending on the browser's version. Message passed by Web Worker is accessed using onmessage event in the main page.

👉 Note: : postMessage() can accept either a string or JSON object as its single argument.

Example:

<html>
   <head>
      <title>ABCD</title>
      
      <script>
         var worker = new Worker('process.js');
         
         worker.onmessage = function (event) {
            alert("Completed " + event.data + "iterations" );
         };
         
         function sayHello() {
            alert("Hello sir...." );
         }
      </script>
   </head>
   
   <body>
      <input type = "button" onclick = "sayHello();" value = "Say Hello"/>
   </body>
</html>

Process.js

for (var i = 0; i <= 1000000000; i += 1) {
   var j = i;
}
postMessage(j);

Stopping Web Workers

Web Workers don't stop by themselves but the page that started them can stop them by calling terminate() method.

Syntax:

worker.terminate();

A terminated Web Worker will no longer respond to messages or perform any additional computations. We cannot restart a worker. Instead, we can create a new worker using the same URL.

Checking for Browser Support

Following is the syntax to detect a Web Worker feature support available in a browser.

<html>
   <head>
      <title>ABCD</title>
      <script src = "modernizr-1.5.min.js"></script>
      
      <script>
      function myFunction() {
         
         if (Modernizr.webworkers) {
            alert("Congratulation!! you have web workers support." );
         } else {
            alert("Sorry!! you do not have web workers support." );
         }
      }
      </script>
   </head>
   
   <body>
      <button onclick = "myFunction()">Click me</button>
   </body>
</html>

Types of Web Workers

1. Dedicated Workers

A dedicated worker is only accessible by the script that calls it. Creating a new worker is simple. All we need to do is call the Worker() constructor, specifying the URI of a script to execute in the worker thread.

var myWorker = new Worker('worker.js');

2. Shared Worker

A shared worker is accessible by multiple scripts — even if they are being accessed by different windows, iframes or even workers. Spawning a new shared worker is pretty much the same as with a dedicated worker, but with a different constructor name.

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

One big difference is that with a shared worker we have to communicate via a port object — an explicit port is opened that the scripts can use to communicate with the worker (this is done implicitly in the case of dedicated workers).
The port connection needs to be started either implicitly by use of the onmessage event handler or explicitly with the start() method before any messages can be posted. Calling start() is only needed if the message event is wired up via the addEventListener() method.


Points to Remember


  • If SharedWorker can be accessed from several browsing contexts, all those browsing contexts must share the exact same origin (same protocol, host, and port).
  • In Firefox, shared workers cannot be shared between documents loaded in private and non-private windows.
  • When using the start() method to open the port connection, it needs to be called from both the parent thread and the worker thread if two-way communication is needed.
  • The onmessage and postMessage() need to be hung off the Worker object when used in the main script thread, but not when used in the worker.

Questions

1. Which method terminates a web worker?

terminate()
stop()
end()
None of the options
The terminate() terminates a web worker.