I'm trying to make a function call some code while allowing my main function to continue and not have to wait for it.
So far it's not working:
function doSomething() {
return new Promise((resolve, reject) => {
if(1) {
console.log("doing something");
for(let i = 0; i < 10000; i++) {
for(let j = 0; j < 10000; j++) {
for(let k = 0; k < 100; k++) {
// Do something for a long time to check if async is working
}
}
}
console.log("finished doing something");
resolve( {"dummydata": 10} );
}
else {
reject("error!");
}
})
}
function main() {
doSomething()
.then(data => console.log(data))
.catch(err => console.error(err))
console.log("this should print before doSomething() is finished");
}
main();
This is the output:
doing something
finished doing something
this should print before doSomething() is finished
{ dummydata: 10 }
Why is my program waiting for doSomething()? I want it to run in parallel / asynchronously. I also tried making main() an async function, same with doSomething(), but that didn't work.
JavaScript is still single-threaded. If you have an expensive segment of code, like your nested loop, and you don't await inside the loop, all other JavaScript processing in your environment will be blocked while the loop iterates - control flow will only yield back once all the synchronous code has finished.
Code put at the top level of the Promise constructor callback runs immediately - doing return new Promise doesn't make the code be put on a separate thread, or something like that.
While you could queue the task so it starts after a delay, and lets the main script continue whatever it needs to do:
function main() {
setTimeout(doSomething, 2000);
// more code
To truly run it in parallel, you'll need to use a child_process. Put the expensive section of the script into its own file, and have child_process invoke it via .fork.
You can use worker_threads: https://nodejs.org/api/worker_threads.html#worker-threads
const { Worker } = require("worker_threads");
const worker = new Worker(
`
const { parentPort } = require('worker_threads');
parentPort.postMessage("doing something");
for (let i = 0; i < 10000; i++) {
for (let j = 0; j < 10000; j++) {
for (let k = 0; k < 100; k++) {
// Do something for a long time to check if async is working
}
}
}
parentPort.postMessage("finished doing something");
parentPort.postMessage({ dummydata: 10 });
`,
{ eval: true }
);
worker.on("message", (message) => console.log(message));
console.log("this should print before doSomething() is finished");
This is just a snippet. You can exchange data with worker and so on...