You only have one thread to work with in the main event loop, so there's no way to have long CPU intensive tasks that don't block if they run in that thread. Node allows various ways of spawning threads and processes. Here's one way to take the loop and put it into a new thread.
const { Worker, isMainThread, parentPort, workerData} = require('worker_threads');
if (isMainThread) {
function doAsyncThing(n) {
return new Promise(resolve => {
const worker = new Worker(__filename, {workerData: {n}});
worker.on('message', resolve);
});
};
// run two loops in parallel:
doAsyncThing(1)
.then(res => console.log("got response from thread1:", res))
doAsyncThing(2)
.then(res => console.log("got response from thread2:", res))
} else {
const {n} = workerData;
let res = jsSum(n)
parentPort.postMessage(res);
}
function jsSum(n){
console.log("jsSume started for call ", n)
let a = 0;
for(let i = 0; i < 100; i++){
console.log(`worker ${n} in loop ${i}`)
a += 1;
}
let total = a;
return total;
}
If you watch the logs you will see the loops running together in parallel like:
worker 1 in loop 1
worker 1 in loop 2
worker 1 in loop 3
worker 1 in loop 4
worker 2 in loop 1
worker 2 in loop 2
worker 1 in loop 5
After the calls to doAsyncThing()
your main thread is free for other things like responding to requests. Also (fwiw) console.log()
is not a great tool for demonstrating this since the logs are sent to the main thread.