NodeJs & Firebase nested forEach async await











up vote
0
down vote

favorite












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.










share|improve this question




























    up vote
    0
    down vote

    favorite












    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.










    share|improve this question


























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      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.










      share|improve this question















      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.







      node.js firebase asynchronous firebase-realtime-database async-await






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 7 at 17:43









      Frank van Puffelen

      220k25361387




      220k25361387










      asked Nov 7 at 16:34









      sseggio

      254




      254
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          0
          down vote













          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





          share|improve this answer




























            up vote
            0
            down vote













            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) {

            }
            });





            share|improve this answer





















              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














               

              draft saved


              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53193836%2fnodejs-firebase-nested-foreach-async-await%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              0
              down vote













              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





              share|improve this answer

























                up vote
                0
                down vote













                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





                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  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





                  share|improve this answer












                  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






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 7 at 17:14









                  Shubham Chaudhary

                  365




                  365
























                      up vote
                      0
                      down vote













                      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) {

                      }
                      });





                      share|improve this answer

























                        up vote
                        0
                        down vote













                        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) {

                        }
                        });





                        share|improve this answer























                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          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) {

                          }
                          });





                          share|improve this answer












                          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) {

                          }
                          });






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 8 at 23:49









                          Reza Nasiri

                          916




                          916






























                               

                              draft saved


                              draft discarded



















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53193836%2fnodejs-firebase-nested-foreach-async-await%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              這個網誌中的熱門文章

                              Tangent Lines Diagram Along Smooth Curve

                              Yusuf al-Mu'taman ibn Hud

                              Zucchini