Reputation: 75
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:
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).
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.
Upvotes: 0
Views: 933
Reputation: 1435
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) {
}
});
Upvotes: 0
Reputation: 499
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
Upvotes: 1