0

I have the following JS code

async function readAtlasAll() {
  return await MongoClient.connect(url, async function(err, db) {
    var dbo = db.db("Users");
    c = dbo.collection("List");
    r = await c.find({}).toArray();
    console.log(r);
    return r;
  });
}

console.log(readAtlasAll());

I'm not sure why, but printing the result of readAtlasAll() comes before printing the variable r inside the function, even though I'm awaiting the result of r beforehand. The terminal prints Promise { <pending> } first and afterwards prints the contents of r. I'm relatively new to JavaScript, so I would really appreciate the help. Thanks!

1 Answers1

2

You cannot use both await and a plain callback on MongoDB API calls as the await won't do anything useful. Use one or the other, not both. This is because the MongoDB asynchronous APIs will return a promise if you do NOT pass a callback to them and you can then await that promise, but if you pass a callback, they do not return a promise, therefore the await does nothing useful at all. Here's how you would implement it by leaving out the callback and using await:

async function readAtlasAll() {
    const db = await MongoClient.connect(url);
    const dbo = db.db("Users");
    const c = dbo.collection("List");
    const r = await c.find({}).toArray();
    return r;          // this will be the resolved value of the returned promise
}

readAtlasAll().then(r => {
   console.log(r);
}).catch(err => {
    console.log(err);
});

Keep in mind that await has no magic powers at all. ALL it does is suspend execution of the function until a promise resolves/rejects. So, it only does anything useful when you await a promise.

And, further, ALL async functions return a promise so there is NO way to return an asynchronously-retrieved value directly from your function. You have to use an asynchronous mechanism for communicating back an asynchronously retrieved value such as a promise, a callback or an event. So readAtlasAll() can never return your value directly.

See How to return the response from an asynchronous call for more info on that.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 1
    You can, it's just done differently. – BGPHiJACK Apr 15 '22 at 20:08
  • @BGPHiJACK - I don't understand that comment. Feel free to write your own answer if you have a better way to write this code or provide a specific suggestion for me to improve this answer. – jfriend00 Apr 15 '22 at 20:11
  • Your answer works but the question was to return an awaited result as a variable in JavaScript and this can in fact be done with callbacks and/or either both, it's not hard to introduce at all if necessary for the development. – BGPHiJACK Apr 15 '22 at 20:15
  • @BGPHiJACK - There is NO way in Javascript to return an asynchronously retrieved value directly from this `readAtlastAll()` function such that the OP's `console.log(readAtlasAll());` will show the result. If you think you have a way for `console.log(readAtlasAll());` to show the result, please write an answer and show us. Javascript simply doesn't work that way with asynchronous operations. Yes, you could pass a callback into `readAtlastAll()`, but that's not returning the value from the function-that's the older mechanism for communicating asynchronous results which is in my answer. – jfriend00 Apr 15 '22 at 20:37