Hi I am pretty new to Nodejs and Express.
I have two endpoint /addcar /viewcar
I made an infinite loop to run whenever post call is sent to /addcar and simultaneously tried to hit /viewcar to check whether it is working parallelly. But the request to /viewcar is timed out. so I added the async key word to check too. still same problem.
app.post('/addcar',async function(req,res){
console.log(req.body);
let a =100;
while(a>10){
console.log("iterating");
}
res.end();
})
app.get('/viewcar',(req,res)=>{
res.send('hello');
})
but /viewcar must work parallelly even though one endpoint function running continuously right? what am I doing wrongly? sorry if the question is silly.
CodePudding user response:
Node.js is single threaded. Therefore any long loops will block the entire process. An infinite loop will definitely block the server.
The long-standing advice in node.js is don't block the event loop!
If you need to execute a long-running process you need to either break it up into multiple chunks that allows the event loop to run (eg. using setTimeout()
) or spawn a new thread using web workers.
This single-threaded nature of node.js is not a bug. It is intentional and is what makes node.js fast and lightweight. While multithreading does naively solve the parallelism issue it has the cost of context switching and high memory usage (which in turn can potentially also cause slowdowns due to allocating memory and garbage collection).
Splitting long-running process into asynchronous chunks
As hinted at above, you can split long running loops into chunks and run them asynchronously. The classic way is to use setTimeout
or setInterval
:
function infiniteLoop (message) {
console.log("iterating" message);
setTimeout(()=>infiniteLoop(message), 10); // run 100 times per second
}
app.post('/addcar',async function(req,res){
console.log(req.body);
infiniteLoop(JSON.stringify(req.body));
res.end();
})
You can make the code look more like a loop by Promisifying the setTimeout
function and using async/await
:
function sleep (timeout) {
return new Promise(ok => setTimeout(ok, timeout));
}
app.post('/addcar',async function(req,res){
console.log(req.body);
let a =100;
while(a>10){
console.log("iterating");
await sleep(10); // this allows the event loop to run
}
res.end();
})
Most things that take a long time are already async
In general though, unless you're trying to calculate the 1000th digit of π (pi) most of the things that require you to wait a long time are already asynchronous. Therefore doing things like reading from a file or making a database query will not block the process:
app.post('/addcar',async function(req,res){
console.log(req.body);
// This does not block other endpoints:
let data = await db.query('select * from products');
res.json(data);
})
The reason this is possible is because waiting for I/O does not use the CPU at all. Therefore node.js is able to execute other javascript code (eg. other endpoints) while the data is transferred over the wire to your PC.
Basically the only time you need to worry about this is when you need to run long for
or while
loops. All other cases are already automatically handled for you.