1

I am trying to create an array of key-value pairs in a dynamic fashion. The values part is fetched from the database inside my routes. This is what I am doing.

   router.get('/account',isAuthenticated, function(req,res){
   var following_users_details = [];

    for (var i = 0;i<req.user.following_users.length;i++)
    {
        var following_user = req.user.following_users[i];// following_users is a field of Array type in my MongoDB database 
        User.findOne({'username' : following_user },
            function(err,user)
            {
                following_users_details.push({
                    username: user.username,
                    profilepic : user.photo,
                    userbio : user.bio
                });
            });
    }
    res.render('users/userAccount',{user:req.user, following_users_details:following_users_details });
});

But when I try to print my array of key-value pairs I get nothing.

for(var i = 0;i<following_users_details.length;i++)
{
    console.log("Username = "+following_users_details[i].username);
    console.log("Username = "+following_users_details[i].profilepic);
    console.log("Username = "+following_users_details[i].userbio);
}

Nothing gets outputted on the console when I try to print the array. I think I am missing something very obvious. Is this the proper way of creating the array or am I doing it in a wrong way?

P.S. - I have already gone through this , this and this, but none of these address my issue directly.

4
  • 1
    Nothing pretty obvious from the code, can you put a console.log(JSON.stringify(user)) line just at the beginning of the function(err,user){..} to check the user document returned from MongoDB? Commented Mar 14, 2015 at 8:46
  • 2
    Guess it's because fetch from DB it's async operation Commented Mar 14, 2015 at 8:46
  • @chridam The user document is getting returned. It's not null. I checked it. Commented Mar 14, 2015 at 9:30
  • @marsh Okay, I get that. Is there any way of achieving this? Commented Mar 14, 2015 at 9:35

2 Answers 2

3

The callback in findOne happens in the future, it is async. You must render inside said callback for the data to exist.

   User.findOne({'username' : following_user },
        function(err,user)
        {
            following_users_details.push({
                username: user.username,
                profilepic : user.photo,
                userbio : user.bio
            });
            res.render('users/userAccount',{user:req.user, following_users_details:following_users_details });
        });
}
Sign up to request clarification or add additional context in comments.

1 Comment

If I do this, I get another error. Can't set headers after they are sent. Any other way of doing it?
1

A few things, first one that your console.log happens before they come from db.

Second, and better, do not do all the unnecessary calls per user, make just one call for all of this.

router.get('/account',isAuthenticated, function(req,res){
  var following_users_details = [];

  User.find({
    username:
      {$in: req.user.following_users} // assuming this is an array
  }, {
    // select options. This might be done differently though,
    // depending on your MongoDB driver/ORM
    username: true,
    profilepic: true,
    userbio: true
  },
  // callback
  function (err, followedUsers) {
    // only now you have access to users, not before. Now log/send them
    if (err) {/* handle DB error */

    res.render('users/userAccount',{
      user:req.user,
      following_users_details: followedUsers
    });
    // also log them to console.
    followedUsers.forEach(function(followedUser) {
       console.log(JSON.stringify(followedUser, null, 2);
    });
  });
});

Comments

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.