How to Do Multithreading In JavaScript?

How to Run or Call Executable (EXE) From JavaScript?

Want to learn how to perform or do multithreading in Javascript? JavaScript is a single-threaded language, meaning that only one line of code can be executed at once. How does then JavaScript handle high volumes of traffic on modern web applications?

JavaScript’s single-threaded nature can present numerous issues, particularly when combining long-running tasks with UI components. This nature may result in the webpage freezing due to a CPU-intensive task blocking the UI components, creating a significant vulnerability for our web application 😪.

Although JavaScript is primarily single-threaded, it can simultaneously execute multiple tasks by leveraging asynchronous programming techniques. The said techniques include callbacks, promises, and async/await.

These methods allow for non-blocking input/output operations, enabling JavaScript to work around its limitations and complete multiple tasks concurrently.

But it’s not just the web pages! JavaScript is used for much more. For example, it can conduct intensive computations and create complex visuals.

However, these tasks take time, blocking the thread and slowing down UI events. So more than the asynchronous techniques discussed before are required. To do this, you can move the processing from your application to the server side (a web server) or use multithreading.

A fundamental change in language structure would be required to add concurrency – it can’t simply be added on 🤔!

In 2009, JavaScript developed a new technology called “Web Workers” to address the issue of multi-threaded code. This article covers how to implement multi-threading in JavaScript using Web Workers. You will also find out why and when it should be used 🙂!

What Is Multithreading?

Multi-threading is a computer programming technique that allows a single process or program to have multiple threads of execution, each of which handles a specific task. It can be used to improve the performance of programs by allowing different tasks to be executed simultaneously on different processors, such as when running on a multiprocessor system.

What Are Web Workers In JavaScript?

Web Workers are JavaScript scripts that run in the background, separate from the main thread of an HTML page. They allow multiple tasks to be performed simultaneously by creating two or more threads. In addition, messages can transfer data between the main thread and the workers.

Web Workers are JavaScript scripts that run in the background

However, Web Workers enable complex operations to take place in the background without affecting the performance of the main page. It enables simulations that could run independently and do not block Document Object Model (DOM).

Why Might Developers Choose To Use JavaScript Web Workers?

When you need to do complex computations in response to a button click, web workers can help you! Instead of tying up all the resources and preventing users from scrolling or clicking anything on the website, web workers operate quietly in the background.

It allows users to continue using the website without interruption or displaying the dreaded “this website is unresponsive” error message. In addition, JavaScript multithreading is enabled when this background work takes place on another thread, so take advantage of it!

You could allow users to input data in the browser and pass the variables to the worker to perform computations in the background. Meanwhile, users can do other tasks on the main thread. When done, the worker returns the result, which can be printed on the page. Multiple issues can be worked on simultaneously, with solutions passed back out of order as resolved.

Note that the workers need to familiarize themselves with the context or setting. Then, they acquire relevant information in the form of a message, as mentioned before.

Interestingly, there is no need to worry about concurrent access to shared variables, which can be challenging in multithreading systems. This is because of different contexts; Web Workers should not be considered parallel processing.

How Can You Exchange Data With Web Workers?

Data transfer between the main thread and web workers occurs via messages. Messages are sent using postMessage() and received via an onmessage event handler, with the message stored in the data parameter. As a result, data passed between the main thread and workers are duplicated. As a result, it impacts memory allocation and transmission speed.

Data transfer between the main thread and web workers occurs via messages.

The following is pseudo-code that illustrates this process. In the file containing code for the main thread, the worker is created,

//main.js
const myWorker = new Worker('worker.js');myWorker.postMessage({
attribute1: 'data1',
attribute2: 'data2',
});

This is the message being posted is an object with two attributes, attribute1 and attribute2, and their corresponding values, ‘data1’ and ‘data2’ respectively.

Next, you can create as many workers as you want. In the file containing code for let’s say worker 1 thread, use postMessage() as following,

onmessage = function(e) {
postMessage(result);
};

Instead of onmessage, one can simply use addEventListener() callback.

self.addEventListener("message", e => {})

This data exchange process invokes the Structured Clone Algorithm to clone that incoming object. This algorithm creates a duplicate of the object by recursively looping through it.

How Simple Web Workers Work In Practice?

Let’s have worker.js and main.js, where worker.js is a “Worker.” It executes the command on a separate thread. Both main.js and worker.js can exchange data back and forth, as mentioned above. Let’s see how to set it up!

Here is the use case to understand it better.

Imagine a group of friends excited to go to the movies. Some people purchased their tickets in advance, while others did not, intending to do so once they arrived. When they arrived, the security guard demanded tickets. Those who had pre-booked tickets were processed quickly, but those who did not have to purchase then checked. The excitement grows as they all enter, ready to enjoy the show.

The issue here is that if a person has to buy a ticket, they and all the other people after them must wait. This is called the ‘blocking‘ behavior. However, JavaScript can handle this situation by handling asynchronous calls. But what if this registration process is so complex that it causes even asynchronous calls to delay the execution?

Here comes the use of Web Workers!

Step 1: Create A Folder And Add Index.Html

Following is the code to display people who booked the tickets in advance and doesn’t have to wait for entry.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Security Checkpoint</title>
</head>
<body>
<h2>Welcome to the Cinema!</h2>
<ul id="pre-booked"></ul>
<script src="./main.js"></script>
</body>
</html>

Step 2: Create Main Thread

The following main thread is created in main.js. The code below contains the details of each person in the group. The data of each person is passed on to the worker which can cause delays. At the same time, the main thread execution continues with other members.

//This is the array of friends going to cinema (true: pre-booked tickets, false: hasn't pre-booked tickets
const friends = [
    {
      name: "Marcelo",
      hasTicket: true,
    },
    {
      name: "James",
      hasTicket: false,
    },
    {
      name: "Chris",
      hasTicket: true,
    },
    {
      name: "Eliza",
      hasTicket: false,
    },
  ]
 
const hasTicket = document.getElementById("pre-booked")

let worker;

//This function decides the entry
function entry(friends) {
  friends.forEach(person => {
    const { name, isMember } = person;
    const listItem = document.createElement("li");
    listItem.textContent = name;

    //People who are not members first buy tickets
    if (!isMember) {
      //Such people are assigned to Worker
      const worker = new Worker("worker.js");
      worker.postMessage(person);

      //Listen to the Worker
      worker.onmessage = (e) => {
        if (e.data) {
          //If the person has booked a ticket, add his/her name to the list
          hasTicket.appendChild(listItem);
        }
      };
    } else {
      //If the person already has a ticket, directly let them in and add their name to the final list
      hasTicket.appendChild(listItem);
    }
  });
}

entry(friends);

A list hasTicket is initialized to have the final output, which is the order in which friends enter the cinema.

In the function entry(), a new worker is created for the person who has yet to book a ticket in advance. Then, the person object is sent to the worker via worker.postMessage(). Next, the worker.onmessage event handler listens for return messages from the worker. If a message is received and is true (e.g. e.data is true), their name will be added to the final list of people who have tickets (hasTicket).

For those who booked ticket in advance, their name is directly added to the list of people who have tickets without creating a worker.

Step 3: Create Worker Thread

In worker.js, the worker thread is created. This processes the person who doesn’t have a ticket and sends them back to the main thread to get added to the final list.

//You can also use self.addEventListener to access addEventListener
addEventListener("message", e => {
const person = e.data;
giveTicket(person);
})function giveTicket(person) {
let k = 0
const limit = Math.pow(10, 12);
while (k < limit) {
k++
}
person.hasTicket = true;
//the final result is sent back to the main thread
postMessage(true)
close()
}

Using the addEventListener method, the worker listens for messages sent from the main thread. When a message arrives, the giveTicket function is invoked, which takes a person object as an argument and modifies it by adding an hasTicket property with the true value.

In the giveTicket function, the while loop is used to simulate a time-consuming process. This could represent any intensive computation or I/O operation that needs to be performed in the background.

When the computation is finished, the result is returned to the main thread via the postMessage method, and the worker is terminated via the close method.

Output

Create Worker Thread to Do Multithreading In JavaScript

James, who had not pre-booked a ticket, was the last to enter the cinema, while those who had pre-booked their tickets went in first.

Conclusion

JavaScript’s single-threaded nature can cause performance issues for certain tasks, but Web Workers provide a way to mitigate this by taking advantage of multithreading. It allows code to execute parallel and improves performance while preventing freezing or slowdowns.

So, whether you’re developing a web application or working on a complex computation project, Web Workers are a valuable tool in your arsenal.

Who says JavaScript can’t multitask? It can juggle more threads than a caffeine-fueled spider 🕸️!

Lastly, let us know in the comments:

  • Did you try exchanging data between threads?
  • Can you suggest other use cases that require multithreading?
  • Have you ever encountered challenges or issues when implementing multithreading in your JavaScript projects?

Share this article with your fellow developers so they can learn how to perform multithreading in JavaScript! 👩‍💻

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts
Total
0
Share