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:
Reference: Structured Clone Algorithm