Node.js is a single threaded javascript framework built using Google chrome’s V8 engine and when it comes to concurrency and speed of api’s, node.js is considered one of the top framework. However, if cpu intensive tasks are not handled properly, it will block all the further requests. To solve this issue, we need to understand how to use multithreading in node.js.
To understand the issue, we will implement a simple demo Node.js app. You can skip this if you want solution directly.
Issue in action
Open your favourite text editor. Open terminal and hit
npm init -y && npm i express
Create a server.js file at the root and paste following code in it.
const app = require("express")();
const port = process.env.PORT || 3000;
app.get("/non-blocking/", (req, res) => {
res.status(200).send("This page is non-blocking");
});
app.get("/blocking", async (req, res) => {
let counter = 0;
for (let i = 0; i < 20_000_000_000; i++) {
counter++;
}
});
app.listen(port, () => {
console.log(`App listening on port ${port}`);
});
Open postman or chrome and hit http://localhost:3000/non-blocking, you will see a quick response as there is no cpu intensive task written in the api. Now, call the other api http://localhost:3000/blocking and Immediately call the first api again in two different tabs. Now you will see, first api won’t respond until second api is done with its for loop. This is blocking nature of Node.js.
Solution in action
To tackle this, we can use in built worker_threads module. Now, create a new file worker.js and add following code to it.
const { parentPort } = require("worker_threads");
let counter = 0;
for (let i = 0; i < 20_000_000_000; i++) {
counter++;
}
parentPort.postMessage('counter value is ' + counter);
And change the server.js code with following :
const { Worker } = require('worker_threads');
const app = require("express")();
const port = process.env.PORT || 3000;
app.get("/non-blocking/", (req, res) => {
res.status(200).send("This page is non-blocking");
});
app.get("/blocking", async (req, res) => {
const worker = new Worker('./worker.js');
worker.on('message', (data) => {
res.status(200).send(`${data}`);
})
worker.on("error", (msg) => {
res.status(404).send(`An error occurred: ${msg}`);
});
});
app.listen(port, () => {
console.log(`App listening on port ${port}`);
});
Now, repeat the same api calling processs. Call the blocking api first and immediately call non blocking api in two different tabs. You will see that even if blocking request was not complete yet, non blocking api’s will return their response.
That’s it, we have used two threads to understand how to use multithreading in node.js. You can use all available threads in a same way to carry out such operations in parallel. Thanks for reading.