嵌套NodeJs和Firebase以等待每个异步

时间:2018-11-07 16:34:56

标签: node.js firebase asynchronous firebase-realtime-database async-await

我已经开始学习将NodeJS与Firebase一起使用以创建功能。

我目前陷入困境,因为我嵌套了forEach,它必须是异步的。

我会尽量让自己理解。

我有3个节点:

  • 端子
  • 预订
  • TerminalBookings(就像一个联接表)

我必须创建一个函数来获取所有关联有其预订的终端。

因此,我必须获取所有终端,对于每个终端,我都可以获取所有关联的终端预订(节点密钥是终端ID,所有值都是预订ID)。 enter image description here

然后,当我完成所有终端预订后,就可以在“预订”节点中获取预订信息。

使用Sql看起来很容易,但是我可以弄清楚如何使用NodeJS。

这里是我所拥有的(在这种状态下,无法工作,但看起来像我想做的事):

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

  }
 });

但是由于这一行它无法工作:

const bookingsSnapshot = await getReservationsSnapshotByTerminalId(terminal.key);

如果我要使用await,则父forEach必须异步进行,但这是不可能的。

我认为我处理该功能的方法不正确,但是我被卡住了,我不知道该怎么做。

如果我错了,请随意完全重建此功能。

2 个答案:

答案 0 :(得分:0)

您可以通过以下两种方法之一来实现

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

输出:

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"));

再次输出为:

Terminal1
Terminal2
Terminal3
Done

答案 1 :(得分:0)

怎么样

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

 }
});