-1

I have been trying to understand how async/await keywords and promises work in NodeJs. Below is my test code:

function lowLevelFileReading() {
    for (let i = 0; i < 100000; i++) {
        for (j = 0; j < 100000; j++) {
            let lol = 5;
            lol = lol * lol + 2;
        }
    }
}

function slowPromise() {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log("starting slow promise " + new Date())
            lowLevelFileReading();
            resolve("slow");
            console.log("slow promise is done " + new Date())
        }, 1000);
    })
}

function fastPromise() {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log("starting fast promise" + new Date())
            resolve("fast")
            console.log("fast promise is done" + new Date())
        }, 3000);
    })
}

async function parallel() {
    // Start 2 "jobs" in parallel and wait for both of them to complete
    await Promise.all([
        (async()=>console.log(await slowPromise()))(),
        (async()=>console.log(await fastPromise()))()
    ])
}

parallel();

And here is my console output:

starting slow promise Sun Apr 04 2021 10:41:30 GMT+0300 (GMT+03:00)
slow promise is done Sun Apr 04 2021 10:41:54 GMT+0300 (GMT+03:00)
slow
starting fast promiseSun Apr 04 2021 10:41:54 GMT+0300 (GMT+03:00)
fast promise is doneSun Apr 04 2021 10:41:54 GMT+0300 (GMT+03:00)
fast

In my computer, lowLevelFileReading() takes approximately 25 seconds to complete, so i think it's suitable to test some long running operation.

As you can see in the above, the code in the slowPromise() set to start after 1 seconds, and the code in the fastPromise() set to start after 3 seconds.

I am expecting fast promise to start 2 seconds after slow promise. But it's not happening. You can see in the console output, fast promise does not start until slow promise completely done. Please look at timestamps of console logs.

I think it's not possible to do what i'm trying to do in javascript. But then I don't understand how async file read function in 'fs' library works. I mean, what is the difference in fs.readFile()'s implementation and my imaginary lowLevelFileReading() implementation. Is node treating some "special" methods differently?

I can't imagine how a node.js server used as backend for a web site with millions of users with time consuming operations can be implemented. Can you please provide some insights?

Yusuf K
  • 13
  • 5
  • Promises can be said to run concurrently - not in parallel. Javascript is single threaded and `lowLevelFileReading` is blocking the execution until it's finished. You may want to look into [`Workers`](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) if you have a genuinely computationally expensive task. – Emissary Apr 04 '21 at 08:30

1 Answers1

-1

Quick disclaimer: I just read this and I might explain things a bit wrong.

The problem is that Node.js normally runs single threaded. But when running some sort of non-javascript operation it can "outsource" it and make it run parallel on the Kernel. But when you have a function like lowLevelFileRead in your case, which doesn't run any sort of I/O operation it will be blocking the execution of other code.

Here is an article I found, which may help explain things:

https://medium.com/@mohllal/node-js-multithreading-a5cd74958a67

MrCodingB
  • 2,284
  • 1
  • 9
  • 22
  • With your version of code, fast promise still does not start until lowLevelFileReading() completed. – Yusuf K Apr 04 '21 at 08:25
  • This doesn't solve the problem of the `lowLevelFileReading` function being slow and *blocking*, it just adds a delay after that slow, blocking function has run before resolving the promise. – Quentin Apr 04 '21 at 08:28
  • "Putting it into the timeout makes it run asynchrounously." — No, it doesn't. It just makes it run 3 seconds later. It is still slow and blocking. Other stuff could run *before* it, but not at the same time as it. – Quentin Apr 04 '21 at 08:34
  • But the fast promise starts before the reading operation – MrCodingB Apr 04 '21 at 08:35
  • 1
    Running the fast promise first isn't the point, the point is that `lowLevelFileReading` blocks everything else *while* it is running no matter when that might be. – Quentin Apr 04 '21 at 08:36
  • Hmm...I'll take another look – MrCodingB Apr 04 '21 at 08:37