Open In App

Power of Web Workers – Multithreading in JavaScript

Last Updated : 26 May, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Web Workers are a browser API that allows JavaScript to execute tasks in parallel on a separate thread. It enables the main thread to continue running without being blocked, allowing the user interface to remain responsive. A Web Worker runs in a separate global context, meaning it has its own JavaScript engine instance, and therefore cannot directly access the variables or functions of the main thread. Instead, Web Workers communicate with the main thread using a message-passing system.

Creating a Web Worker: To create a Web Worker, we can use the Worker constructor function. The Worker constructor takes a URL as its argument, which is the path to the worker script file. However, since we want to include the worker code within the HTML file, we can use a blob to create the worker code.

Syntax:

const worker = new Worker('worker.js');

Communicating with Web Workers: Once we’ve created a web worker, we can send and receive messages between the main thread and the worker thread using the postMessage() method and the onmessage event handler.
This code snippet sends a message from the main thread to a web worker:

// Create a new web worker
const myWorker = new Worker("worker.js");

// Send a message to the worker
myWorker.postMessage("Hello, worker!");

In this code snippet, we’ve created a new web worker and sent a message to it using the postMessage() method. To receive messages from the web worker, we need to add an event listener to the onmessage event. Here’s the code snippet for receiving a message from a web worker:

// Create a new web worker
const myWorker = new Worker("worker.js");

// Receive a message from the worker
myWorker.onmessage = function (event) {
    console.log(event.data);
};

In this code snippet, we’ve created a new web worker and added an event listener to the onmessage event. When the web worker sends a message back to the main thread, the onmessage event handler is called and the message is logged to the console.
Example 1: (Combining all the code pieces described above): Calculate the factorial of a number, say 10. We can use a Web Worker to perform this calculation in a separate thread, like this:

HTML




<!DOCTYPE html>
<html>
  
<head>
    <title>Web Workers Example</title>
    <style>
        body {
            text-align: center;
        }
  
        h1 {
            color: green;
        }
    </style>
</head>
  
<body>
    <h1>GeeksforGeeks</h1>
  
    <h2>Web Workers Example</h2>
  
    <p>
        Calculate the factorial of 10 using a 
        web worker to prevent blocking the UI 
        thread.
    </p>
  
    <div id="result"></div>
  
    <script>
        const worker = new Worker(URL.createObjectURL(new Blob([
            `
            // Worker script
            const factorial = (n) => {
                if (n == 0 || n == 1) {
                    return 1n;
                } else {
                    return BigInt(n) * factorial(BigInt(n) - 1n);
                }
            };
                       
            self.onmessage = (event) => {
                const result = factorial(event.data);
                self.postMessage(result.toString());
            };`
        ], { type: "text/javascript" })));
  
        worker.postMessage(10n);
  
        worker.onmessage = (event) => {
            const result = event.data;
            document.getElementById("result").innerHTML
                = `Factorial of 10 is ${result}`;
        };
    </script>
</body>
  
</html>


Output:

 

Exaplanation: In this example, we create a new Web Worker by instantiating the Worker class with the URL of a new Blob object that contains the code for the worker. The code for the worker is defined in an anonymous function that calculates the factorial of a number using a recursive function. The worker listens for messages sent from the main thread using the self.onmessage event calculates the factorial of the input number and sends the result back to the main thread using the self.postMessage method.

In the main thread, we create a new worker instance and send a message to it containing the number 10n (the n suffix indicates that this is a BigInt value). Once the worker has finished calculating the factorial, it sends the result back to the main thread using the postMessage method. The main thread receives the result in the onmessage event and updates the HTML content of the result div element with the calculated value.

Example 2: This example prints the primes till number n. This example allows the user to enter a number and then calculate all prime numbers up to that number using a web worker. The worker script checks if each number is prime and returns an array of all prime numbers to the main thread for display in the resulting paragraph.

HTML




<!DOCTYPE html>
<html>
  
<head>
    <meta charset="UTF-8">
    <title>Web Worker Example</title>
    <style>
        body {
            text-align: center;
        }
  
        h1 {
            color: green;
        }
    </style>
</head>
  
<body>
    <h1>GeeksforGeeks</h1>
  
    <h2>Web Worker Example</h2>
  
    <p>
        This example shows how to use a web
        worker to perform a long-running task
        without blocking the main thread.
    </p>
  
    <p>
        Enter a number below to find all prime
        numbers up to that number.
    </p>
  
    <input type="number" id="num" min="1">
    <button onclick="startWorker()">Start</button>
    <button onclick="stopWorker()">Stop</button>
    <p id="result"></p>
  
    <script>
  
        // Create a new worker
        let worker;
  
        function startWorker() {
            const num = document.getElementById("num").value;
            if (num === "") {
                alert("Please enter a number");
                return;
            }
  
            worker = new Worker("data:text/javascript;base64,"
                + btoa(workerScript));
  
            // Send message to worker
            worker.postMessage(num);
  
            // Listen for message from worker
            worker.onmessage = function (event) {
                document.getElementById("result").innerHTML =
                    event.data.join(", ");
            };
        }
  
        function stopWorker() {
            worker.terminate();
        }
  
        // The script to be executed in the worker
        const workerScript = `
            function isPrime(num) {
                if (num < 2) {
                    return false;
                }
               
                for (let i = 2; i < num; i++) {
                    if (num % i === 0) {
                        return false;
                    }
                }
               
                return true;
            }
               
            onmessage = function(event) {
                const num = parseInt(event.data);
                const primes = [];
               
                for (let i = 2; i <= num; i++) {
                    if (isPrime(i)) {
                        primes.push(i);
                    }
                }
               
                postMessage(primes);
            };`;
    </script>
</body>
  
</html>


Output:

 

Benefits of Web workers:

  • Enable multithreading in JavaScript
  • Improve performance by performing computationally intensive tasks in separate threads
  • Prevent blocking the main thread, resulting in a more responsive user experience

Drawbacks of using web workers:

  • Increased memory consumption
  • Communication overhead between the main thread and workers
  • Overall, web workers are a valuable addition to the JavaScript language, providing a solution to the problem of blocking the main thread. By taking advantage of web workers, developers can create faster and more responsive web applications, improving the user experience for their audience.

Conclusion: One important point to note is that using web workers can also have drawbacks. Since workers are separate threads of execution, they can increase the memory consumption of the application. Additionally, communication between the main thread and workers can introduce overhead, which can slow down the application. Therefore, it is important to carefully consider the use of web workers and use them only when necessary. To conclude, web workers are a powerful tool that can enable multithreading in JavaScript, allowing us to perform computationally intensive tasks without blocking the main thread. By leveraging web workers, we can significantly improve the performance of our web applications, creating faster and more responsive user experiences.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads