0

I am trying to iterate data from DB and then pushing that data to an array. I did 2 console.log: 1 inside the loop and the other outside the loop. However, the one outside the loop got printed first with an empty array. But why and how does this happen? Everything seems to be looking fine :( Need help, please!

This is what I have:

app.get("/greybook/:bookid", (req, res) => {
    const usernameArr = [ ];
    Book.findById(req.params.bookid, (error, foundBook) => {
        for(let associate of foundBook.associates) {
            User.findById(associate, (error, foundUser) => {
                usernameArr.push(foundUser.username);
                console.log(usernameArr); // 1st console.log here...
            });
        }
        console.log(usernameArr); // 2nd console.log here...
        res.render("greybook/greybookshow", {book: foundBook, associates: usernameArr});    
    });
});

And this is the output from the console:

[ ]
[ 'grey_ghost' ]
[ 'grey_ghost', 'gerry' ]
[ 'grey_ghost', 'gerry', 'ghost' ]

1 Answer 1

1

It's because the callback in Book.findById is not going to wait for the asynchronous call to User.findById, since it is already resolved at that point. I would rewrite this using async/await, which allows you to avoid "callback hell" and see the flow of the code more easily. Try this:

app.get("/greybook/:bookid", async (req, res) => {
  const usernameArr = [];
  let foundBook = await Book.findById(req.params.bookid);
  for (let associate of foundBook.associates) {
    let foundUser = await User.findById(associate);
    usernameArr.push(foundUser.username);
    console.log(usernameArr); // 1st console.log here...
  });
  console.log(usernameArr); // 2nd console.log here...
  res.render("greybook/greybookshow", {
    book: foundBook,
    associates: usernameArr
  });
});

Sign up to request clarification or add additional context in comments.

5 Comments

@GreyGhost don't forget to accept this answer if it fully answers your question or ask for more details if that would help.
Would you suggest to stop using callbacks for everything and use async/await instead?
@GreyGhost yes async/await is the preferred method in modern JavaScript. There is no need to use callbacks anymore.
Last question. So if we want handle errors, simply put try catch on top of everything is that correct?
@GreyGhost you could do try/catch on each controller function, but there's more elegant ways to do. It's too much to describe in a comment, but I recommend you check out this repo as an example: github.com/wesbos/app

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.