0

I've started learning NodeJS to use it with Firebase in order to create Functions.

I'm currently stuck because I have nested forEach which must be async.

I'll try to be as understandable as possible.

I have 3 nodes:

  • Terminals
  • Bookings
  • TerminalBookings (which is like a join table)

I have to create a function to get all the terminals with their bookings associated.

So I have to get all the terminals, for each terminal I can get all the terminalbookings associated (the node key is the terminal id and all the values are bookings id). enter image description here

And then when I have all the terminalbooking, I can get the booking informations in the bookings node.

It look pretty easy to do with Sql but I can figure out how to do it with NodeJS.

Here is what I have (in this state, it's impossible to work, but it looks like what I want to do):

async function getReservationsSnapshotByTerminalId(terminalId) {
  const terminalReservationsSnap = await admin.database().ref(`/terminalBookings/${terminalId}`).once('value');
  const terminalReservations = Object.keys(terminalReservationsSnap.val());

  const reservationsSnapshot = terminalReservations.map((reservationId) => {
    return admin.database().ref(`/bookings/${reservationId}`).once('value');
  });

  return Promise.all(reservationsSnapshot);
}

exports.showTerminalsWithReservations = functions.https.onRequest(async (request, response) => {
  let terminals = [];
  try {
    const terminalsSnapshot = await admin.database().ref('/terminals/').once('value');

    terminalsSnapshot.forEach(terminalSnapshot => {
      const terminal = new Borne(terminalSnapshot.key, terminalSnapshot.val());
      const bookingsSnapshot = await getReservationsSnapshotByTerminalId(terminal.key);

      bookingsSnapshot.forEach(booking => {
        terminal.bookings.push(booking.val());
      });
      terminals.push(terminal);
    });
  } catch(error) {

  }
 });

But it can't work because of this line :

const bookingsSnapshot = await getReservationsSnapshotByTerminalId(terminal.key);

If I want to use the await, the parent forEach must by async but it's not possible.

I think that I'm not in the right way to handle this feature but I'm stuck, I don't know how to do it.

Feel free to completely rebuild this function if I'm wrong.

2 Answers 2

1

You can achieve that with either of following 2 ways

for await (let terminal of terminals){
   await getReservationsSnapshotByTerminalId(terminal.terminalId);
   console.log(terminalId);
}
console.log("Done");

Output:

Terminal1
Terminal2
Terminal3
Done

OR

var promise = Promise.all(terminals.map((terminal) => {
  console.log(terminal.id);
  return await getReservationsSnapshotByTerminalId(terminal.id);
}));

promise.then(() => console.log("Done"));

Again output is:

Terminal1
Terminal2
Terminal3
Done
Sign up to request clarification or add additional context in comments.

Comments

0

how about this

const getReservationsSnapshotByTerminalId = (terminalId) => {
     return admin.database().ref(`/terminalBookings/${terminalId}`).once('value')
       .then(snapshot => {
          const terminalReservations = Object.keys(terminalReservationsSnap.val());
          const reservationsSnapshot = terminalReservations.map(reservationId => {
               return admin.database().ref(`/bookings/${reservationId}`).once('value');
       });
       return Promise.all(reservationsSnapshot);
     });
};

exports.showTerminalsWithReservations = functions.https.onRequest(async (request, response) => {
     let terminals = [];
     try {
        terminals = await admin.database().ref('/terminals/').once('value')
           .then(snapshot =>{
               const promises = [];
               const allTerminals = snapshot.val();
               const terminalKeys = Object.keys(allTerminals);
               const terminalsArray = terminalKeys.map(key => new Borne(key, allTerminals[key]));
               promises.push(terminalsArray);
               promises = promises.concat(terminalKeys.map(key => getReservationsSnapshotByTerminalId(key)));
               return Promises.all(promises);
           })
          .then(resultArray => {
               const terminalsArray = resultArray[0];
               terminalsArray.forEach((terminal, idx) => {
                  const bookingsSnapshot = resultArray[idx + 1];
                  bookingsSnapshot.forEach(booking => {
                      terminal.bookings.push(booking.val());
                  });
               });
               return terminalsArray;
         });


} catch(error) {

 }
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.