Get fullData when CollectionGroup is found

Viewed 110

I have a problem querying all data from 1 collection User-> UidUser-> InfoUser (POST (Collection), name, age ...)

I then used the code below to get the collectionsGroup (Post) but how do I get the User's Name and age?

When I use 2 nested loops, another problem is that forEach cannot use Await and Async inside it makes me lose data.

  getData = async () => {

        await firebase.firestore().collection('user').doc(Fire.shared.uid).onSnapshot(documentSnapshot => {

            firebase.firestore().collectionGroup('Post').where('uid', 'in', 
                documentSnapshot.data().Followings).get().then(querySnapshot => {

                const Post = [];
                  querySnapshot.forEach(post => {


                    Post.push({ data: post.data() }) // This is correct and get full data's Post


                });
                this.setState({ dataPost: Post })
            })
        })
}

await firebase.firestore().collection('user').doc(Fire.shared.uid).onSnapshot(documentSnapshot => {

            firebase.firestore().collectionGroup('Post').where('uid', 'in', documentSnapshot.data().Followings).get().then(querySnapshot => {

                const Post = [];

                querySnapshot.forEach(async (post) => {
                    // Incorrect because forEach don't wait callback => Lose a documents's user //
               
                   await firebase.firestore().collection('user').doc(post.data().id).onSnapshot(user => {

                    Post.push({ data: post.data(),user: documentSnapshot.data() })

                    })
                });
                this.setState({ dataPost: Post })
            })
        })
1 Answers

I think promise.all resolve this problem

firebase.firestore()
.collection("user")
.doc(Fire.shared.uid)
.onSnapshot((documentSnapshot) => {
  firebase
    .firestore()
    .collectionGroup("Post")
    .where("uid", "in", documentSnapshot.data().Followings)
    .get()
    .then((querySnapshot) => {
      const Post = [];

        querySnapshot.forEach((post) => {
            Post.push(new Promise((resolve, reject) => {
                firebase
                .firestore()
                .collection("user")
                .doc(post.data().id)
                .onSnapshot((user) => {
                  resolve({ data: post.data(), user: documentSnapshot.data() });
                });
          }))
       
      });
        Promise.all(Post).then(res => {
          console.log(res)
        this.setState({ dataPost: res})

     })
    });
});

I show how it's work with a simple example with setTimeout function & forEach function maybe it helps others when facing this kind of problems

async function call() {
  const nums = [1, 2, 3, 4, 5];
  const promises = [];
  nums.forEach((res) => {
    setTimeout(() => {
      promises.push(res*2);
    }, 10000);
  });
  console.log(promises);
}
call();

async function call() {
  const nums = [1, 2, 3, 4, 5];
  const promises = [];
  nums.forEach((res) => {
    setTimeout(() => {
      promises.push(res*2);
    }, 10000);
  });

  Promise.all(promises).then((res) => {
    console.log("res", res);
  });
}
call();

in the above examples, output was an empty array so I figure out a way to fix this issue

   
async function call() {
  const nums = [1, 2, 3, 4, 5];
  const promises = [];
  nums.forEach((res) => {
    promises.push(
      new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(res * 2);
        }, 3000);
      })
    );
  });

  Promise.all(promises).then((res) => {
    console.log("res", res);
  });
}
call();

Related