Open In App

How to run a function in a separate thread by using a Web Worker in JavaScript ?

Last Updated : 29 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

JavaScript is a popular lightweight, interpreted compiled client-side scripting language. Most Web Applications use JavaScript on the client side. By providing JavaScript with a runtime environment, it can also be used on the server-side (Node.js). In this article, we will cover how to run a function on a separate thread by using a JavaScript Web Worker.

Pre Requisites:

What is a Web Worker?

Many languages such as Java, C++ etc have the functionality of multi-threading. A web worker simply allows us to use the functionality of multi-threading in JavaScript. If any time-consuming function is blocking the DOM, we can use web workers to run it in the background keeping the DOM clutter-free.

Obstacles Faced by Web Workers:

  • A Web Worker does not have access to the DOM.
  • Data that cannot be reproduced can’t be passed to the web worker. More precisely data that cannot be cloned with the structured clone algorithm, can’t be passed to the web worker.

Passing a function to a web worker is a challenging task, as a function cannot be cloned by the structured clone algorithm. A DataCloneError is thrown when a function is passed to a web worker. 

The trick to passing functions to a web worker:

Step 1: Convert the function to be passed into a string by using the toString() method. Strings can be passed to a web worker as they can be duplicated by the structured clone algorithm. The below code converts the function to a string.

myString = myFunction.toString()

Step 2: Pass the string to the web worker.

Step 3: Convert the string back to a function inside the web worker by using the Function() constructor. The below code converts the string back to a function.

convertedFunction = new Function("return" + myString)();

Step 4: Evaluate the function.

Example: We are going to move the text GeeksForGeeks randomly. The random position is calculated by the web worker. We are going to create two files, one for the DOM and one for the web worker. 

index.html: Edit index.html in the following manner:

HTML




<!DOCTYPE html>
<html lang="en">
  
<body style="height: 90vh; width: 93vw;">
    <h1 style="color: #2f8d46; position: absolute;">
        GeeksForGeeks
    </h1>
  
    <script>
  
        // Updated the position on the DOM
        const updatePosition = (element, randomPosition) => {
            element.style.top = randomPosition[0] + "px";
            element.style.left = randomPosition[1] + "px";
        }
  
        // Calculates the random position
        const getRandomPosition =
            (height, width) =>
                [(Math.floor(Math.random() * height)),
                Math.floor(Math.random() * width)];
  
        // Creating a Web Worker
        const worker = new Worker('worker.js');
  
        // Getting the GeeksForGeeks text
        const title = document.querySelector('h1');
  
        // Updated the position on receiving 
        // the random position
        worker.onmessage = (event) =>
            updatePosition(title, event.data);
  
        // Passing the function to the Web Worker
        worker.postMessage({
  
            // Converting the function to a string
            function: getRandomPosition.toString(),
  
            // Arguments passed to the function
            arguments: [document.body.offsetHeight,
            document.body.offsetWidth, 1000]
        })
    </script>
</body>
  
</html>


worker.js: Edit worker.js in the following manner:

Javascript




self.onmessage = ({data}) => {
  
    // Converting the string back to a string
    const func = new Function(
        "return" + data.function
    )();
  
    // Evaluates the function and sends
    // the data back to the main file
    const timerFunction = () => {
        randomPositions = func(
            data.arguments[0], data.arguments[1]
        );
        self.postMessage(randomPositions);
    }
  
    // Runs the timerFunction at every 
    // interval specified in the arguments.
    setInterval(() => {
        timerFunction();
    }, data.arguments[2])
  
}


Output:

GeeksForGeeks switching to random positions on the DOM

Reference: Structured Clone Algorithm



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads