1

I'm trying to populate an array of posts with various mongoDB documents.

app.get('/dash/:id', isLoggedIn, (req, res) => {
    var posts = [];
    User.findById(req.params.id, (err, user) => {
      user.follows.forEach((followId) => {
        User.findById(followId, (err, follow) => {
          follow.posts.forEach((postId) => {
            Post.findById(postId, (err, post) => {
              posts.push(post);
            })
          })
        })
      })
    })
    console.log(posts)
  })

My problem is that the final console.log produces an empty array, but if I call console.log(posts) immediately after pushing each document into the array, everything is working fine. I'm sure there's something stupid that I'm missing. Is it running my console.log before it completes the data lookup? Thanks in advance!

  • `findById` is async. Dupe of https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron – JohnnyHK Apr 15 '18 at 00:14

1 Answers1

0

mongoose's finById is asynchronous, the code will execute other stuff ( like console.log ) while fetching the data, but it returns a promise, so make use of that and avoid the callback hell you're having, and you can use find() with conditions instead of multiple findById() being called multiple time in loops,

i don't know what does your schema looks like but ideally you would use populate to avoid the second .find() and maybe add a ref to posts but here a suggestion based on your post :

try this :

app.get('/dash/:id', isLoggedIn, (req, res) => {

    User.findById(req.params.id).select('follows -_id') // this will return an array of follows
    .then((follows) => {
        return User.find({ _id : follows}).select('posts -_id') // this will retrun an array of posts Ids
    })
    .then((postsIds) => {
        return Post.find({ _id : postsIds}); // these are your posts        
    })
    .then((posts) => {
        console.log(posts); // do stuff with posts here, res.render() maybe ?
    })

});
Taki
  • 17,320
  • 4
  • 26
  • 47