s3niot
s3niot

Reputation: 1

Response getting sent before foreach completed

I'm trying to get a Firestore collection with its subcollections. Therefore, I wrote a Firestore Cloud Function. But when I send a request, I'm getting an empty array back. The console log displays the data after the response is sent.

Can anyone explain me: What am I doing wrong?

And I know that the code is not best practice but if there is anyone who has a better idea how to get the data. I would appreciate to hear it. Thank you

My code:

export const helloWorld = functions.https.onRequest((request, response) => {
  cors(request, response,() => {
    getProfiles()
      .then((data) => {
        console.log(data)
        response.send(data)
      })
      .catch((err) => {
        console.log(err)
      })
  })
})

const getProfiles = async (): Promise<any[]> => {
  const allTrainers: any[] = []
  const trainerProfiles = await db.collection('consultant_profiles').get()

  trainerProfiles.forEach(async (snapshot: DocumentSnapshot) => {
    const profile = snapshot.data()

    if (profile) {
      profile['.key'] = snapshot.id
    }

    const trainerPackets = await db
      .collection('consultant_profiles')
      .doc(snapshot.id)
      .collection('consultant_packets')
      .orderBy('price', 'asc')
      .get()

    const packets: any[] = []
    trainerPackets.forEach((packet: DocumentSnapshot) => {
      packets.push(packet.data())
    })

    const trainerReviews = await db
      .collection('consultant_profiles')
      .doc(snapshot.id)
      .collection('consultant_reviews')
      .get()

    const reviews: any[] = []
    trainerReviews.forEach((review: DocumentSnapshot) => {
      reviews.push(review.data())
    })

    allTrainers.push(profile, packets, reviews)

    console.log(profile, packets, reviews)
  })

  return allTrainers
}

The logs:

[]
9:21:44.586 PM
helloWorld
Function execution took 2717 ms, finished with status code: 200
9:21:44.889 PM
helloWorld
[]
9:21:44.893 PM
helloWorld
Function execution took 1291 ms, finished with status code: 200
9:21:49.268 PM
helloWorld
{ updatedAt: Timestamp { _seconds: 1568747857, _nanoseconds: 790000000 }, first_name: 'Torben', services: [ 'nutrition', 'fitness', 'health' ], description: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.', image_url: 'https://www.fillmurray.com/360/360', last_name: 'Müller', '.key': 'VajLDpnbNPPJ3WjR0tKRBZ8bKX63' } [ { userId: 'VajLDpnbNPPJ3WjR0tKRBZ8bKX63', description: 'Drittes Paket ALL INC', price: 89, createdAt: Timestamp { _seconds: 1568747856, _nanoseconds: 878000000 } } ] []

Upvotes: 0

Views: 60

Answers (1)

Niko Modric
Niko Modric

Reputation: 665

You can use Promise.all as follows:

...

await Promise.all(trainerProfiles.map(async (snapshot: DocumentSnapshot) => {
    ...
    return true;
}))

return allTrainers

I hope it would help you.

Upvotes: 2

Related Questions