0

I want to rewrite the variable output inside the async function(user). I tried after the .forEach(async function (user) to add .then and finally() but the console.log(output) stays everywhere empty.

async function findData() {
    const client = await MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true })
      .catch(err => { console.log(err); });
    if (!client) {
      return;
    }
    try {
      var code = "";
      const db = client.db(dbname);
      let collection = db.collection('user');
      let res = await collection.find(status: 'open').forEach(
        async function (user) {
          output = "User: " + user._id + " - " + await city(user.city) + output;
        });
        console.log(output); // the result is here ""
    } catch (err) {
      console.log(err);
    } finally {
      console.log(output); // the result is here ""
      client.close();
      return;
    }
  }
findData();

Is there a way to await the async function (user)?

Mq77
  • 39
  • 1
  • 5
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Liam Oct 13 '20 at 14:58
  • "the variable code" you mean "the variable output"? `forEach` doesn't await callbacks, it's sync. Use e.g. `for ... of` with an `await`, you'll be happier. – ASDFGerte Oct 13 '20 at 14:58
  • also [Using async/await with a forEach loop](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop) – Liam Oct 13 '20 at 14:59
  • So I can use the variable `res` (the result of the `await collection.find`) to generate the variable `output` and reuse it `output` then? – Mq77 Oct 13 '20 at 15:06

1 Answers1

0

I'm not sure what you are looking to do since you talk about rewriting the variable code but you are printing output and not reassigning code.

However, what you should know is that in javascript .forEach is not asynchronous. It doesn't wait for the async function to terminate and triggers everything at the same time. Use a for loop instead like:

let res = await collection.find(status: 'open');
for (user of res) {
    output = "User: " + user._id + " - " + await city(user.city) + output;
    console.log(output);
}
Liam
  • 27,717
  • 28
  • 128
  • 190
Valentin Vignal
  • 6,151
  • 2
  • 33
  • 73
  • I'm sorry I mean the variable "output".(edited now) When I `console.log(res);` it says `null` so I never tried your suggestion, I will try it out. Can reuse the variable `output` or does it stay inside the `for()`-block? – Mq77 Oct 13 '20 at 15:12
  • When I try it with `for of` I get the error `TypeError: res is not iterable`. :( – Mq77 Oct 13 '20 at 15:22
  • In your example `output` is not define in your for loop (no `let` or `const` keyword, so I assume it was defined before in your code and therefore you can use it outside the loop. However if you only define it in the loop, you can only use it in the loop. Do `let output` before – Valentin Vignal Oct 14 '20 at 01:47
  • Actually, I don't know what is the type of `res` maybe res is actually no the object you want to iterate on but `res.documents` or whatever? You can also try a classic `for` loop `for (let i=0; i – Valentin Vignal Oct 14 '20 at 01:49