DEV Community

Arshia.Saleem for One Beyond

Posted on

Multithreading in the DOM in JavaScript

JavaScript is a single-threaded language, which means only one script can be run at a time. Working with your UI Dom and performing complicated computations can occasionally result in issues that cause apps to run slowly or appear unresponsive.

It is common to get confused between multithreading and asynchronous programming. Since asynchronous tasks are non-blocking and can be performed concurrently, they are not dependent on one another. But they are still using single-thread.

To use Multithreading for complex calculations, here comes the concept of web workers.

Example used for this article can be found in the following link

What is a web worker?

A web worker is a JavaScript process that runs in the background,separate from the main thread of a web page. The main thread is the default JavaScript thread, which we refer to as a single thread.
This is responsible for running all the JavaScript for a web page as one line at a time. So basically, a web worker allows you to execute multiple threads of JavaScript in parallel with each other. To avoid the main thread doing all the heavy lifting itself, a web worker can be created and used to offload expensive work, so the main thread can continue executing other code. To be aware, there is one disadvantage that can be faced: that a web worker can’t be used to manipulate the DOM, only the main thread can access the DOM and manipulate it.

How and where can we use a web worker and run it parallelly with the main thread?

Now, as we know what a web worker is, we will see how and where it can be implemented and used.Here is a simple example:

web-worker-example

We have two buttons: one for doing a sum and the other to change the background color. If we try to calculate the sum and immediately try to change the background color, it may cause a block up of the main thread. As we can see below, for loop is an expensive operation and we have only one thread that is working on the sum calculation, so it will prevent any other operations until it’s finished with the for loop.

const sumButton = document.getElementById("sumButton");
const backgroundButton = document.getElementById("backgroundButton");
sumButton.addEventListener("click", function () {
  let sum = 0;
  for (let index = 0; index < 10000000000000; index++) {
    sum += index;
  }
  alert(`total sum ${sum}`);
});


backgroundButton.addEventListener("click", function () {
  if (document.getElementById("container").style.backgroundColor != "blue") {
    document.getElementById("container").style.backgroundColor = "blue";
  } else {
    document.getElementById("container").style.backgroundColor = "green";
  }
});
Enter fullscreen mode Exit fullscreen mode

To avoid this problem , we can create web workers that will work in parallel in a way that the web worker and the main thread will be communicating with each other to pass the data. In order to use it,we can create an instance.
We will define the constructor for web worker as following:

const worker = new Worker("worker.js");

As previously shown in the image, the worker constructor takes the path of worker script,so first, we will need to create a file where we will define the work that worker will do. Once created, we need to understand how we can pass the data to and from the main script and the worker. The way we pass or offload the data to the worker is by using the method postMessage(). Essentially, the post message raises an event from one script that other scripts can listen to. We can set up an event listener on worker script in the following way to listen for new post messages:

self.onmessage= function(message){}

Here, we are creating an event handler, so whenever we get a new post message ,the worker needs to do something.
Now in order to solve the problem we previously mentioned of executing heavy loop to calculate the sum, we will move the code to worker script:

self.onmessage = function (message) {
  let sum = 0;
  for (let index = 0; index < 10000000000000; index++) {
    sum += index;
  }
  this.postMessage(sum);
};

Enter fullscreen mode Exit fullscreen mode

In this way, the worker will simultaneously do all the sums in the background process to avoid blocking up the main thread. The problem here is the worker will be doing the sum, but it’s not actually telling the main thread whenever it’s done. So, for that we will use postMessage(). The worker is sending the sum to the main thread through the postMessage() and the main script will catch the message:

onmessage = function (message) {
  let sum = 0;
  for (let index = 0; index < 10000000000000; index++) {
    sum += index;
  }
  this.postMessage(sum);
};
Enter fullscreen mode Exit fullscreen mode
worker.onmessage = function (event) {
  alert(`Total Sum: ${event.data}` );
};

Enter fullscreen mode Exit fullscreen mode

Main thread script will look like this:

const worker = new Worker("worker.js");

const sumButton = document.getElementById("sumButton");
const backgroundButton = document.getElementById("backgroundButton");

sumButton.addEventListener("click", function () {
  worker.postMessage("Sum Button clicked");
});

worker.onmessage = function (event) {
  alert(`Total Sum: ${event.data}` );
};
backgroundButton.addEventListener("click", function () {
  if (document.getElementById("container").style.backgroundColor != "blue") {
    document.getElementById("container").style.backgroundColor = "blue";
  } else {
    document.getElementById("container").style.backgroundColor = "green";
  }
});
Enter fullscreen mode Exit fullscreen mode

To conclude, despite the fact that JavaScript is a single thread, we can still use web workers to run our tasks concurrently and in an efficient way without affecting the main thread.

Bibliography

Multithreading in Javascript Using Worker Threads
Multithreading Javascript

Top comments (10)

Collapse
 
dustytrinkets profile image
Laura

Super interesting article! Great job Arshia!

Collapse
 
arshiasaleem98 profile image
Arshia.Saleem

Thank you so much!!!😊

Collapse
 
iamaravindkumar profile image
Aravind Kumar J

Very informative Thanks 👍

Collapse
 
arshiasaleem98 profile image
Arshia.Saleem

Thank you so much😊

Collapse
 
baumannzone profile image
Jorge Baumann

Love it! 😍

Collapse
 
arshiasaleem98 profile image
Arshia.Saleem

Thank you so much 😊

Collapse
 
sarahokolo profile image
sahra 💫

Wow super informative 🌟👍

Collapse
 
arshiasaleem98 profile image
Arshia.Saleem

Thanks a lot.😊

Collapse
 
eliaspereyra profile image
Elías Pereyra

Thanks, great article!

Collapse
 
arshiasaleem98 profile image
Arshia.Saleem

Thanks a lot😊