Skip to content
Related Articles

Related Articles

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

View Discussion
Improve Article
Save Article
  • Last Updated : 03 Mar, 2022
View Discussion
Improve Article
Save Article

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.js: Edit index.js in the following manner:

index.js

<!DOCTYPE html>
<html lang="en">

<body style="height: 90vh; width: 93vw;">
    <h1 style="color: #2f8d46; position: absolute;">
        GeeksForGeeks
    </h1>
</body>

<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>

</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

 


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!