0

I have three functions

async function inventories() { 
  print("starting inventories")
  sleepFor(5000)
  // Here I am querying a mongodb database
  const inventoriesRes = await db.inventories.find({})
  return inventoriesRes
}

async function costs() { 
  print("starting costs")
  const costsRes = await db.costs.find({})
  return costsRes
}

async function users() {
  print("starting users")
  const users = await db.users.find({})
  return usersRes
}

I want :

  1. The queries to be all executed in //
  2. Once all are finished, print the results

Here's my solution

const dbqueries = async () => {
  const [result1, result2, result3] = await Promise.all([inventories(), costs(), users()])

  return {result1, result2, result3}
}

dbqueries.then(results => {
  print(JSON.stringify(results))
}).catch(error => {
  throw error
});

The problem is that I am not this solution works as I want. To verify, I've put a sleep (see code below) in the inventories() function. What's happening is

printing starting inventories
waiting for 5 seconds
printing costs
printing users

This let me think that costs() didn't start in parallel. If it had started earlier, I would have

printing starting inventories
printing costs
printing users 
...
function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ 
        /* Do nothing */ 
    }
}

Either my solution is wrong, or the sleepFor function is doing something more than just putting to sleep only the inventories() function. Any help?

PS. print works exactly like console.log() in mongoshell which is a fully-functional JS interpreter

BloodyOrange
  • 165
  • 5

1 Answers1

1

…or the sleepFor function is doing something more than just putting to sleep only the inventories() function

Precisely that. You've wrote a synchronous, blocking sleep function, which stops the entire program. You've called it before any await in the function, so it's not even sleeping later while the concurrent work is already under way, you're sleeping before inventories() returns its promise and the other two functions can get called.

Your original program did work as expected. For verification, you should have added another print statement to log when each database call is finished:

async function inventories() { 
  print("starting inventories")
  // Here I am querying a mongodb database
  const inventoriesRes = await db.inventories.find({})
  print("finished inventories")
  return inventoriesRes
}

Remember that JS code does not run in parallel, on multiple threads or anything. All you can do is to start multiple asynchronous tasks (in your case the database queries), without immediately waiting for each to finish. Rather, you start them all, then wait for the results while they do their work concurrently.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Okay great! Thanks for your answer. Since you've said" it's not even sleeping later while the concurrent work is already under way, you're sleeping before inventories() returns its promise", I am wondering when exactly does the function `inventories` return its promise? – BloodyOrange Jun 29 '22 at 19:21
  • An `async` function does return the promise to its caller when coming across the first `await` or `return`. – Bergi Jun 29 '22 at 19:22
  • okay one last question, if one of my functions, say `inventories` throws an exception, then the Promise.all will stop without finishing executing other functions and since I have `dbqueries.then(results => { print(JSON.stringify(results)) }).catch(error => { //The code is this bloc will be executed in case one of the functions throw an exception });` it's the `catch` bloc that will be executed, right ? – BloodyOrange Jun 29 '22 at 19:26
  • Yes, as soon as any of the promises rejects, `Promise.all` will ignore the other ones and the `catch` callback will run immediately. Notice that `Promise.all` is not "executing" the functions, the functions were called by your code and did return promises which then were passed into `Promise.all` - it only *waits* for those promises to settle – Bergi Jun 29 '22 at 19:34