A web worker is a JavaScript code that runs in the background and does not influence the page’s performance.
As we know, JavaScript is a single-threaded language, meaning that it can only process one task at a time.
let t = new Date();console.log(`tastk 1 took: ${new Date() - t}ms`);console.log(`tastk 2 took: ${new Date() - t}ms`);console.log(`tastk 3 took: ${new Date() - t}ms`);
In the example given above, we will see the following output in the console, in the same sequence:
tastk 1 took: 0ms
tastk 2 took: 1ms
tastk 3 took: 2ms
Because these tasks are simple, when we open the console, we’ll see that all three lines have been printed with almost no time in between them.
But what if one of these tasks took a longer time than the others?
let t = new Date();console.log(`tastk 1 took: ${new Date() - t}ms`);console.log(`tastk 2 took: ${new Date() - t}ms`);let i = 0;while (i <= 1000000000) {i++;}console.log(`tastk 3 took: ${new Date() - t}ms`);
It will take much longer to run task 3.
Note: The browser may issue a warning, for instance, “this page is slowing down your browser.” In that case, the page will be frozen until the calculation is complete.
The first button is a simple counter, which begins counting as soon as we click it.
The other button is a piece of code that takes a long time to run.
When we click it, we’ll see that the counter and the rest of the page are frozen until the calculation is completed.
This is where web workers come in to help.
If a process is likely to take a long time, the user is not expected to wait until it is complete. A long waiting time results in a poor user experience.
Therefore, such long tasks should be performed in the background.
We will create another button called Worker Calculation
.
Now, we will move the logic of the long calculation to a separate file named worker.js
.
Instead of alerting the value directly, we will use the postMessage
method.
Then, we will create a workerCalculation
function and do the following:
onmessage
callback that takes an event as an argument.We’ll use this callback
to alert the data that comes from the postMessage
method when the calculation is complete.
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><title>Web Workers</title><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><!-- counter --><script>let i = 0;let intervalId = null;const counter = () => {if (!intervalId) {intervalId = setInterval(() => {i++;document.getElementById("counter").innerText = i;}, 300);} else {clearInterval(intervalId);i = 0;document.getElementById("counter").innerText = i;intervalId = null;}};</script><!-- longCalculation --><script>const longCalculation = () => {let i = 0;while (i <= 10000000000) {i++;}alert("Long calculation finished!");};</script><!-- workerCalculation --><script>const workerCalculation = () => {let worker = new Worker("worker.js");worker.onmessage = (e) => {alert(e.data);};};</script></head><body><h3>Counter: <span id="counter"> # </span></h3><button onclick="counter()">Start Counter</button><button onclick="longCalculation()">Long Calculation</button><button onclick="workerCalculation()">Worker Calculation</button></body></html>
Not all browsers support web workers.
We need to check whether or not the user’s browser supports web workers, before creating one:
if (typeof Worker !== "undefined") {
// Yes!
} else {
// No!
}
Hence, our worker.js
file should be:
if (typeof Worker !== "undefined") {
let i = 0;
while (i <= 1000000000) {
i++;
}
postMessage("Worker calculation finished!");
} else {
alert("Your browser doesn't support web workers.");
}
Note: Download the final GitHub Repo.