Home » HTML5 Web Workers Tutorial

HTML5 Web Workers Tutorial

by shedders

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:

  1. What are Web Workers?
  2. Setting up a Web Worker.
  3. Sending and receiving messages.
  4. Using Web Workers for intensive tasks.
  5. 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

  1. Offload Heavy Tasks: Use workers for CPU-intensive tasks only.
  2. Keep Workers Lightweight: Avoid bloated scripts; workers are sandboxed and do not have access to the DOM.
  3. Use Termination: Always terminate workers when no longer needed.
  4. 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:

  1. How to set up and use Web Workers.
  2. How to handle communication between the main thread and workers.
  3. Use cases like prime number checking and multi-task workers.
  4. Best practices for efficient worker usage.

Web Workers are a powerful feature in HTML5 that enhances performance and responsiveness.

You may also like