I\'m having a hard time getting a promise chain to flow correctly in a firebase cloud function. It loops through a ref and returns an array of emails for sending out notific
Instead of dealing with all the promises from the inner query inline and pushing the emails into an array, you should be pushing the promises into an array and using Promise.all()
to wait until they're all done. Then, iterate the array of snapshots to build the array of emails.
You may find my tutorials on working with promises in Cloud Functions to be helpful in learning some of the techniques: https://firebase.google.com/docs/functions/video-series/
The following should do the trick.
As explained by Doug Stevenson in his answer, the Promise.all()
method returns a single promise that resolves when all of the promises, returned by the once()
method and pushed to the promises
array, have resolved.
exports.reminderEmail = functions.https.onRequest((req, res) => {
const currentTime = new Date().getTime();
const future = currentTime + 172800000;
const emails = [];
// get the main ref and grab a snapshot
return ref.child('courses/').once('value') //Note the return here
.then(snap => {
const promises = [];
snap.forEach(child => {
var el = child.val();
// check for the 'members' child, skip if absent
if(el.hasOwnProperty('members')) {
promises.push(admin.database().ref('courses/' + child.key + '/members/').once('value'));
}
});
return Promise.all(promises);
})
.then(results => {
const emails = [];
results.forEach(dataSnapshot => {
var email = dataSnapshot.val().email;
emails.push(email);
});
console.log('Sending to: ' + emails.join());
const mailOpts = {
from: 'me@email.com',
bcc: emails.join(),
subject: 'Upcoming Registrations',
text: 'Something about registering here.'
}
return mailTransport.sendMail(mailOpts);
})
.then(() => {
res.send('Email sent')
})
.catch(error => { //Move the catch at the end of the promise chain
res.status(500).send(error)
});
})