Web Workers in HTML5 provide a way to run JavaScript in the background, independently of the user interface. This allows you to perform computationally intensive tasks without blocking the main thread, ensuring a smooth user experience.
In this tutorial, you’ll learn:
- What are Web Workers?
- Setting up a Web Worker.
- Sending and receiving messages.
- Using Web Workers for intensive tasks.
- Advanced use cases and best practices.
1. What Are Web Workers?
Web Workers enable background threads to run JavaScript code:
- Dedicated Workers: Used by a single script.
- Shared Workers: Can be shared between multiple scripts.
- Service Workers: Specialized workers for caching and offline capabilities (beyond the scope of this tutorial).
Benefits:
- Keeps the main thread free for UI updates.
- Ideal for tasks like data processing, mathematical computations, or fetching data.
2. Setting Up a Web Worker
Basic Example: Dedicated Web Worker
Web Workers are created in a separate JavaScript file and communicated with using postMessage and onmessage.
Step 1: Create the Worker Script (worker.js)
// worker.js
self.onmessage = function (e) {
const result = e.data * 2; // Example: Multiply input by 2
self.postMessage(result);
};
Step 2: Use the Worker in Your HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Web Worker Example</title>
</head>
<body>
<h1>Basic Web Worker</h1>
<input type="number" id="inputNumber" placeholder="Enter a number">
<button id="startWorker">Start Worker</button>
<p id="output">Result: </p>
<script>
const worker = new Worker('worker.js');
const inputNumber = document.getElementById('inputNumber');
const output = document.getElementById('output');
const startWorker = document.getElementById('startWorker');
startWorker.addEventListener('click', () => {
const number = parseInt(inputNumber.value, 10);
if (isNaN(number)) {
output.textContent = 'Please enter a valid number.';
return;
}
// Send data to the worker
worker.postMessage(number);
// Receive the result from the worker
worker.onmessage = function (e) {
output.textContent = `Result: ${e.data}`;
};
});
</script>
</body>
</html>
Explanation:
- postMessage(data): Sends data to the worker.
- onmessage: Listens for messages from the worker.
- self.postMessage(data): Sends data back to the main script.
3. Using Web Workers for Intensive Tasks
Web Workers shine when performing CPU-intensive tasks, such as computing large numbers.
Example: Prime Number Checker
Step 1: Worker Script (primeWorker.js)
// primeWorker.js
self.onmessage = function (e) {
const num = e.data;
let isPrime = true;
if (num < 2) isPrime = false;
for (let i = 2; i <= Math.sqrt(num); i++) {
if (num % i === 0) {
isPrime = false;
break;
}
}
self.postMessage(isPrime ? `${num} is a prime number` : `${num} is not a prime number`);
};
Step 2: Main HTML File
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Prime Number Checker</title>
</head>
<body>
<h1>Prime Number Checker</h1>
<input type="number" id="number" placeholder="Enter a number">
<button id="checkPrime">Check Prime</button>
<p id="result">Result: </p>
<script>
const worker = new Worker('primeWorker.js');
const numberInput = document.getElementById('number');
const checkPrime = document.getElementById('checkPrime');
const result = document.getElementById('result');
checkPrime.addEventListener('click', () => {
const number = parseInt(numberInput.value, 10);
if (isNaN(number)) {
result.textContent = 'Please enter a valid number.';
return;
}
worker.postMessage(number);
worker.onmessage = function (e) {
result.textContent = `Result: ${e.data}`;
};
});
</script>
</body>
</html>
Explanation:
- The worker performs the prime number calculation in the background.
- The UI remains responsive even for large numbers.
4. Terminating a Web Worker
You can terminate a worker when it’s no longer needed using the terminate method.
Example: Terminate a Worker
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Terminate Worker</title>
</head>
<body>
<h1>Terminate Worker Example</h1>
<button id="startWorker">Start Worker</button>
<button id="stopWorker">Stop Worker</button>
<p id="output">Result: </p>
<script>
let worker;
document.getElementById('startWorker').addEventListener('click', () => {
worker = new Worker('worker.js');
worker.postMessage(5);
worker.onmessage = function (e) {
document.getElementById('output').textContent = `Result: ${e.data}`;
};
});
document.getElementById('stopWorker').addEventListener('click', () => {
if (worker) {
worker.terminate();
document.getElementById('output').textContent = 'Worker terminated.';
worker = null;
}
});
</script>
</body>
</html>
Explanation:
- terminate: Stops the worker, releasing resources.
5. Using Web Workers with Multiple Tasks
Example: Multiple Tasks in a Single Worker
You can use messages to distinguish between tasks.
Worker Script (multiTaskWorker.js)
self.onmessage = function (e) {
const { task, data } = e.data;
if (task === 'square') {
self.postMessage(`Square of ${data} is ${data * data}`);
} else if (task === 'cube') {
self.postMessage(`Cube of ${data} is ${data * data * data}`);
}
};
HTML File
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Multi-Task Worker</title>
</head>
<body>
<h1>Multi-Task Worker Example</h1>
<input type="number" id="number" placeholder="Enter a number">
<button id="squareTask">Calculate Square</button>
<button id="cubeTask">Calculate Cube</button>
<p id="output">Result: </p>
<script>
const worker = new Worker('multiTaskWorker.js');
const numberInput = document.getElementById('number');
const output = document.getElementById('output');
document.getElementById('squareTask').addEventListener('click', () => {
const number = parseInt(numberInput.value, 10);
worker.postMessage({ task: 'square', data: number });
});
document.getElementById('cubeTask').addEventListener('click', () => {
const number = parseInt(numberInput.value, 10);
worker.postMessage({ task: 'cube', data: number });
});
worker.onmessage = function (e) {
output.textContent = `Result: ${e.data}`;
};
</script>
</body>
</html>
Explanation:
- Pass a task identifier in the message to handle multiple tasks.
6. Best Practices for Web Workers
- Offload Heavy Tasks: Use workers for CPU-intensive tasks only.
- Keep Workers Lightweight: Avoid bloated scripts; workers are sandboxed and do not have access to the DOM.
- Use Termination: Always terminate workers when no longer needed.
- Test Browser Support: Ensure Web Worker compatibility across browsers.
7. Browser Support
| Browser | Support |
|---|---|
| Google Chrome | Yes |
| Firefox | Yes |
| Safari | Yes |
| Microsoft Edge | Yes |
| Internet Explorer | Partial (IE10+) |
8. Conclusion
In this tutorial, you learned:
- How to set up and use Web Workers.
- How to handle communication between the main thread and workers.
- Use cases like prime number checking and multi-task workers.
- Best practices for efficient worker usage.
Web Workers are a powerful feature in HTML5 that enhances performance and responsiveness.
