NodeJs и Firebase вложены для каждой асинхронной ожидания - PullRequest
0 голосов
/ 07 ноября 2018

Я начал учить NodeJS использовать его с Firebase для создания функций.

В данный момент я застрял, потому что вложил в forEach, который должен быть асинхронным.

Я постараюсь быть максимально понятным.

У меня есть 3 узла:

  • Терминалы
  • Бронирование
  • TerminalBookings (который похож на таблицу соединений)

Мне нужно создать функцию, чтобы связать все терминалы с их бронированиями.

Таким образом, я должен получить все терминалы, для каждого терминала я могу получить все связанные заказы на терминалы (ключ узла - это идентификатор терминала, а все значения - это идентификаторы заказов). 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 голосов
/ 09 ноября 2018

как насчет этого

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

 }
});
0 голосов
/ 07 ноября 2018

Вы можете достичь этого одним из следующих 2 способов

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
...