1

Below is my async function to read values from DB and logs something on console. But for some reason its not happening.

So, I create an array of promises and then keep waiting for all promises to resolve as promises will read from DB. But await on Promise.all is not pausing the execution of code and not waiting for all promises to resolve instead its passing control back to calling function. Is there anything I am missing here ?

async function readValuesFromDB(codes) {
  console.log('trying to read values from DB');
  let dbPromises = [];
  for(let code in codes) {
    let refId = 'some_random_reference_id_generated_from_codes[i]';
    dbPromises.push(MyDb.getPromise(refId)); // getPromise() returns a promise that reads from DB
  }
  console.log('waiting for all promises to resolve...');

  // waiting for all promises to finish 
  await Promise.all(dbPromises).then((allPromises) => {
    for(let i in allPromises) {
      console.log('OK..read from DB');
    }
  });
  console.log('all promises resolved');

}

console.log('calling readValuesFromDB()');
readValuesFromDB();
console.log('finished readValuesFromDB()');

Output from above call is:

trying to read values from DB
waiting for all promises to resolve...
finished readValuesFromDB
......
......
OK..read from DB
OK..read from DB
OK..read from DB
...
...
all promises resolved

Ideally output should be below (since I am waiting for all promises to resolve using await with Promise.all)

trying to read values from DB
waiting for all promises to resolve...
OK..read from DB
OK..read from DB
OK..read from DB
...
...

So looks like promises are getting resolved after the control is passed back to calling function and seems like await has no effect here.

Any help on why await is not in effect in this case ?

WLKB
  • 11
  • 1
  • 3
  • 1
    When calling `readValuesFromDB()` you are not using an `await`, so it wont wait for the function to be finished there. PS: I would not mix `async/await` and `Promise.then()` syntax. – Sirko May 17 '18 at 12:05
  • @Sirko that means the function in which `readValuesFromDB()` is called should be `async too` ? – WLKB May 17 '18 at 12:11
  • 1
    Either that or use `readValuesFromDB().then( () => console.log('finished readValuesFromDB()') )`. – Sirko May 17 '18 at 12:13
  • @Sirko. You're right with the mixin await/then. It's working but too much emphatic. I've edited my answer accordingly – Bertrand May 17 '18 at 12:35
  • [Don't use `for…in` enumerations on arrays!](https://stackoverflow.com/q/500504/1048572) Also, why are you still using `then` when there is `await`? – Bergi May 17 '18 at 12:46
  • It's generally a bad idea to mix `async / await` with `.then() / .catch()`. The whole point of `async / await` was for you to forget about Promises and write your code *as if it were synchronous*, so you can use a `try {} catch () {}` block. – chharvey Sep 01 '18 at 22:02

3 Answers3

3

The behaviour is normal.

readValuesFromDB is ran async, not console.log('finished readValuesFromDB()');

So console is parsing "finished" before readValuesFrom DB resolves.

You can do like this :

async function readValuesFromDB(codes) {
      console.log('trying to read values from DB');
      let dbPromises = [];
      for(let code in codes) {
        let refId = 'some_random_reference_id_generated_from_codes[i]';
        dbPromises.push(MyDb.getPromise(refId)); // getPromise() returns a promise that reads from DB
      }
      console.log('waiting for all promises to resolve...');
    
      // waiting for all promises to finish 
      let allPromises = await Promise.all(dbPromises);
  for(let i in allPromises) {
    console.log('OK..read from DB');          
  }  
  console.log('all promises resolved');
      console.log('finished readValuesFromDB()');
    }
    
    console.log('calling readValuesFromDB()');
    readValuesFromDB();

or like this :

async function readValuesFromDB(codes) {
  console.log('trying to read values from DB');
  let dbPromises = [];
  for(let code in codes) {
    let refId = 'some_random_reference_id_generated_from_codes[i]';
    dbPromises.push(MyDb.getPromise(refId)); // getPromise() returns a promise that reads from DB
  }
  console.log('waiting for all promises to resolve...');
  
  // waiting for all promises to finish 
  let allPromises = await Promise.all(dbPromises);
  for(let i in allPromises) {
    console.log('OK..read from DB');          
  }  
  console.log('all promises resolved');
  allPromises = ['a', 'b', 'c']; // Dumb values for example
  return allPromises;
}

console.log('calling readValuesFromDB()');
readValuesFromDB().then(response => {
   console.log('finished readValuesFromDB()');
   console.log(response)
});
Bertrand
  • 1,840
  • 14
  • 22
  • But what if I want to fetch the data that is getting resolved in all promises. Will `.then` on `readValuesFromDB` work in this case. haven't tried that yet though. – WLKB May 17 '18 at 12:16
  • You can. You simply need to return your promise.all response. I've edited second example for that – Bertrand May 17 '18 at 12:24
  • I tried your suggestion but I am still getting the same behavior... `await` on `Promise.all` doesn't result in wait for all promises to resolve and control is returned to calling function and thus the results I need after all promises are resolved are available at much later stage in the execution. Not able to understand why await on Promise.all isn't working. – WLKB May 17 '18 at 18:18
  • That's quite weird. Are you in production ? Promise.all is resolved after all promises resolved OR at first promise rejected. Maybe your case ? – Bertrand May 18 '18 at 19:41
3

You are missing an await here:

(async function() {
  console.log('calling readValuesFromDB()');
  await readValuesFromDB();
  console.log('finished readValuesFromDB()');
})();
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • 1
    **This is the correct answer.** There are *many* problems with the OP code, but *this answer* explains why `'finished readValuesFromDB'` was logged before `'all promises resolved'`. In the end, it had nothing to do with `Promise.all()` at all. – chharvey Sep 01 '18 at 22:05
-1

You have to await the call to readValuesFromDB.

console.log('calling readValuesFromDB()');
await readValuesFromDB();
console.log('finished readValuesFromDB()');
Ben West
  • 4,398
  • 1
  • 16
  • 16
  • that means the function in which `readValuesFromDB()` is called should be `async` too ? – WLKB May 17 '18 at 12:11
  • It won't work. Await can only be used in async function : https://stackoverflow.com/questions/43832490/is-it-possible-to-use-await-without-async-in-js – Bertrand May 17 '18 at 12:15
  • Yes, so your solution will not make any difference. I cannot use `await` for `readValuesFromDB` then. – WLKB May 17 '18 at 12:17
  • Then you should return a Promise and use `.then`. – Ben West May 17 '18 at 12:34