Zubaer Rahman
Zubaer Rahman

Reputation: 95

forEach with Firebase call

I am trying to validate a booking by comparing clashes with other bookings (called individually from the db) in a trainer's timetable in a booking site.

I know Firebase calls are asynchronous therefore I need to find a way to wait for all bookings inside the forEach function to be fetched and validated.

I tried placing a flag variable before the forEach and console.logged it at the end of it, but obviously it didn't work as the console.log wouldn't wait for the forEach to complete before running.

I've read about 'async await' but it seems like it would be over-kill for this scenario (?). Could there be an easier way to do this?

Any help appreciated.

                const bookingData = {
                    coursename:this.state.coursename,
                    location:this.state.location,
                    trainerid:this.state.trainerid,
                    startDatetime: this.state.startDatetime,
                    endDatetime: this.state.endDatetime,
                } //FORM DATA I WANT TO VALIDATE


                db.collection('timetables').doc(timetableid).get().then(timetable=>{

                    const data = timetable.data(); //ARRAY OF BOOKING ID'S

                    data.bookings.forEach(bookingid=>{

                        db.collection('bookings').doc(bookingid).get().then(bookingref=>{

                        //FOR EACH 'BOOKING' DOCUMENT IN MY DB, I WANT TO PERFORM THE FOLLOWING OPERATION

                            const booking = bookingref.data().bookingInfo;

                            if( booking.startDatetime.toDate() <= bookingData.startDatetime &&
                                booking.endDatetime.toDate() >= bookingData.startDatetime &&
                                booking.startDatetime.toDate() <= bookingData.endDatetime &&
                                booking.endDatetime.toDate() >= bookingData.endDatetime) {

                                console.log('TIME SLOT UNAVAILABLE')                             
                            }
                            else {
                                console.log('TIME SLOT AVAILABLE')                              
                            }
                        }).catch(err=>console.log(err));

                    });
                })

                // FIND A WAY TO SEE IF THE BOOKING WAS VALID AFTER BEING COMPARED WITH ALL OF THE BOOKINGS IN THE DB

Upvotes: 2

Views: 70

Answers (1)

zord
zord

Reputation: 4783

  1. Change the forEach to a map
  2. Return the promise resulting from that db call inside the map.
  3. Return a boolean where you have the console logs. Let's say true means available.
  4. Now the result of the map will be an array of promises, resolving to all the booleans.
  5. Wait for all of those promises with Promise.all
  6. Put a then after that. It will receive the array of booleans.
  7. If all of those are true, then the time slot is available.

Code:

Promise.all(
  data.bookings.map(
    booking => db....get().then(bookingRef => {
      // return true or false based on your condition
    })
  )
).then(results => {
  // this will wait for all the db calls to complete.
  // and you get all the booleans in the results array.
  const isAvailable = !results.includes(false);
});

Upvotes: 1

Related Questions