frankied003
frankied003

Reputation: 516

Call an async function in foreach loop and return array once loop is done

I'm trying to request data from an API in a foreach loop and push that data to an array and then return that array at the end. Here is my code:

db
            .collection('posts')
            .orderBy('createdAt', 'desc')
            .limit(10)
            .get()
            .then((data) => {
                let posts = [];
                data.forEach((doc) => {
                    db
                        .doc(`/users/${doc.data().userHandle}`)
                        .get()
                        .then((userDoc) => {
                            posts.push({
                                postId: doc.data().id,
                                userHandle: doc.data().userHandle,
                                userImageUrl: userDoc.data().imageUrl,
                                imageUrl: doc.data().imageUrl,
                            });
                        })
                })
                return res.json(posts);
            })
            .catch((err) => {
                console.error(err);
                res.status(500).json({ error: err.code});
            });

From this, the posts array return en empty array or object, even when i replace return res.json(posts) with

.then(() => {
return res.json(posts);
})

Any help is awesome!!!

Upvotes: 0

Views: 45

Answers (1)

antonku
antonku

Reputation: 7665

The array is empty because by the time the response is sent, promises with posts are still pending resolution.

In order to fix this issue, you can collect all the promises in an array using .map(), wait for them to resolve with help of Promise.all() and send the response after that:

db
  .collection('posts')
  .orderBy('createdAt', 'desc')
  .limit(10)
  .get()
  .then((data) => {
    const promises = data.map((doc) => {
      return db
        .doc(`/users/${doc.data().userHandle}`)
        .get()
        .then((userDoc) => {
          return {
            postId: doc.data().id,
            userHandle: doc.data().userHandle,
            userImageUrl: userDoc.data().imageUrl,
            imageUrl: doc.data().imageUrl,
          };
        })
    });
    Promise.all(promises).then(posts => {
      res.json(posts);
    })
  })
  .catch((err) => {
    console.error(err);
    res.status(500).json({ error: err.code});
  });

Upvotes: 2

Related Questions