Multithreading in JavaScript using dedicated workers

13 June 2022



JavaScript in the web browser is single threaded by default, so doing performance intensive tasks and DOM manipulations at the same time can make the application unresponsive and in some cases it might get even worse when the browser shows the message and asks the user to wait or exit the page. We can solve this problem by using web workers.

Web browser shows tab unresponsive error

What is a web worker?

Web worker is a JavaScript code that runs in the background without affecting the performance of the page. There are many types of web workers but we are going to use dedicated workers which spawns real OS-level threads.


Example of using Dedicated Worker

Using a dedicated worker is very simple. First we need to create a separate file for the worker so lets create a file named sample-worker.js:

function isPrime(number) {
    let squareRoot = Math.sqrt(number);
    for (let i = 2; i <= squareRoot; ++i) {
        if (number % i === 0) {
            return false;
        }
    }
    return number > 1;
}

function getPrimeNumbers(min, max) {
    let result = [];
    for (let i = min; i <= max; ++i) {
        if (isPrime(i)) {
            result.push(i);
        }
    }
    return result;
}

onmessage = function(e) {
    console.log('sample-worker: Message received from main script');
    let result = getPrimeNumbers(e.data.min, e.data.max);
    console.log('sample-worker: Posting message back to main script');
    postMessage(result);
}

The onmessage handler allows us to execute some code whenever a message is received. So here in this worker we are generating prime numbers based on the minimum and maximum values provided by the calling thread and returning the result back by calling a postMessage function.


Let's create another file named index.html to communicate with our sample-worker:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dedicated Worker Demo</title>
</head>
<body>
    <script>
        const worker = new Worker('sample-worker.js');
        
        worker.onmessage = function(e) {
            console.log('Message received from sample-worker', e.data);
        };
        
        // Message posted to sample-worker
        worker.postMessage({
            min: 100,
            max: 1000
        });
    </script>
</body>
</html>

In this code we first created the worker instance by calling the worker constructor and specifying the URI of a script to execute in the worker thread:

const worker = new Worker('sample-worker.js');

Then we registered the onmessage handler to receive messages from the worker:

worker.onmessage = function(e) {
    console.log('Message received from sample-worker', e.data);
};

Now at last we posted the message with data to sample-worker by calling the method named postMessage on the worker object:

worker.postMessage({
    min: 100,
    max: 1000
});

This will generate the following output in the developer console:

Output

I hope this article helps you understand the basics of dedicated workers. You can start using them to enhance the user experience of your projects.


Thanks for reading!