Rocky Balboa
Rocky Balboa

Reputation: 814

Use async forEach loop while fetching data from firestore

I have firestore data somewhat like this:

"Support": { "userid":"abcdxyz", "message": "hello" }

I am using nodejs to fetch my data and I also want to show the email address and name of the person who sent this message. So I am using following function:

database.collection("support").get().then(async function (collections) {
var data = [];
console.log("data collected");
collections.forEach(async function (collection) {
    var temp = {};
    var collectionData = collection.data()
    var userInfo = await getUserDetails(collectionData.userId)
    temp.name = userInfo.name
    temp.supportMessage = collectionData.supportMessage
    data.push(temp)
    console.log("data pushed")
});
    console.log("data posted")
    return res.status(200).end(JSON.stringify({ status: 200, message: "Support Message fetched successfully.", data: data }))
}).catch(error => {
    return res.status(500).end(JSON.stringify({ status: 500, message: "Error: " + error }))
});

Here the sequence of logs is following: data collected, data posted, data pushed

I want the sequence like this: data collected, data pushed (x times), data posted

Upvotes: 6

Views: 7672

Answers (3)

kip2
kip2

Reputation: 6873

I know this might not the OP's exact use case but if you're interested in compiling the results of a collection query into an array, you can still use the .docs property of a QuerySnapshot to obtain the list of items:

    ...
    const userId = <some-id>;
    const usersRef = db.collection(`users`)
    const usersSnapshot = await usersRef.where("id", "==", userId).get()

    if (usersSnapshot.empty) {
        console.log('found no matching user ', userId);
        return;
    }

    console.log(`found ${usersSnapshot.size} user records`);

    const userResults = []

    // this block here doesn't construct the results array before the return statement
    // because .foreach enumerator doesn't await: https://stackoverflow.com/q/37576685/1145905
    // usersSnapshot.forEach((doc) => {
    //     // doc.data() is never undefined for query doc snapshots
    //     //console.log(doc.id, " => ", doc.data());
    //     userResults.push[doc.data()];
    // });

    for (user of usersSnapshot.docs) {
        // console.log(user.id, " => ", user.data());
        userResults.push(user.data());
    }
    ...

A more detailed example is here

Upvotes: 4

Rocky Balboa
Rocky Balboa

Reputation: 814

I solved my answer with the help of @estus comment.

Credit: @estus

var data = [];
var tempCollection = [];
collections.forEach(collection => {
    tempCollection.push(collection.data());
});
for (collection of tempCollection) {
    var temp = {};
    var userInfo = await getUserDetails(collection.userId)
    temp.name = userInfo.name
    temp.supportMessage = collection.supportMessage
    data.push(temp)
}

It solved my problem very easily.

Upvotes: 7

Shubham Chaudhary
Shubham Chaudhary

Reputation: 499

Use following code:

database.collection("support").get().then(async function (collections) {
var data = [];
console.log("data collected");

for await(let collection of collections){
  var temp = {};
  var collectionData = collection.data()
  var userInfo = await getUserDetails(collectionData.userId)
  temp.name = userInfo.name
  temp.supportMessage = collectionData.supportMessage
  data.push(temp)
  console.log("data pushed")
}

console.log("data posted")
return res.status(200).end(JSON.stringify({ status: 200, message: "Support Message fetched successfully.", data: data }))
}).catch(error => {
  return res.status(500).end(JSON.stringify({ status: 500, message: "Error: " + error }))
});

OR

Use can use

var promise = Promise.all(collections.map((collection) =>{
   ...
   return await ... //or a promise
}));

promise.then(() => {
  console.log("posted");
  return res.status(200).end(...);
})

Upvotes: 5

Related Questions