-1
router.get("/timeline/:userId", async (req, res) => {
 try {
       
//creating friend posts object

const friendPosts = await Promise.all(
  currentUser.followings.map((friendId) => {
    return Post.find({ userId: friendId });
  })
);

var newFriendPosts = [];

friendPosts.map(async (friend) => {
  friend.map(async (post) => {
    const { profilePicture, username } = await User.findById(post.userId);
    const newFriendPostsObject = {
      ...post.toObject(),
      profilePicture,
      username,
    };
    console.log(newFriendPostsObject);

    newFriendPosts.push(newFriendPostsObject);
  });
});

console.log(newFriendPosts);
// console.log(newUserPosts);
res.status(200).json(newUserPosts.concat(...newFriendPosts));
} catch (err) {
res.status(500).json(err);
 }
});

So the object value is coming correct in console.log(newFriendPostsObject) but when I push that in the array newFriendPosts = []; it shows empty array in console.log(newFriendPosts);

Below is where I am getting user details from DB (DB is in MongoDB):-

const { profilePicture, username } = await User.findById(post.userId);

1 Answers1

1

.map() is NOT async aware. So, it just marches on and returns an array of promises. Meanwhile, your code never waits for those promises so you're trying to use newFriendPosts BEFORE any of your .push() operations have run. .push() is working just fine - you're just trying to use the array before anything has actually gotten around to calling .push(). If you add appropriate console.log() statements, you will see that the newFriendPosts.push(...) occurs after your console.log(newFriendPosts);.

The simplest fix is to change both .map() statements to a regular for loop because a for loop IS async aware and will pause the loop for the await.

router.get("/timeline/:userId", async (req, res) => {
    try {
        //creating friend posts object
        const friendPosts = await Promise.all(
            currentUser.followings.map((friendId) => {
                return Post.find({ userId: friendId });
            })
        );

        const newFriendPosts = [];

        for (let friend of friendPosts) {
            for (let post of friend) {
                const { profilePicture, username } = await User.findById(post.userId);
                const newFriendPostsObject = {
                    ...post.toObject(),
                    profilePicture,
                    username,
                };
                newFriendPosts.push(newFriendPostsObject);
            }
        }

        console.log(newFriendPosts);
        res.status(200).json(newUserPosts.concat(...newFriendPosts));
    } catch (err) {
        res.status(500).json(err);
    }
});

One mystery in this code is that newUserPosts does not appear to be defined anywhere.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • newUserPosts was actually a part of above code which was working since it was not async – Abhishek Sah Apr 06 '22 at 17:10
  • thanks man its working spent like 12 hrs on this – Abhishek Sah Apr 06 '22 at 17:13
  • I doubt this answer is not too good because for of will pause on each await, just create an array of post.userId and using User.findByIds(), finally, using loop again to push data to newFriendPosts, the time to fulfil this function is much more faster – deko_39 Apr 07 '22 at 03:37