我很难让一个承诺链在Firebase云功能中正确流动。它遍历一个ref并返回一系列电子邮件以发送通知。它有一些嵌套的子级,我认为这就是我要出错的地方,但是我似乎找不到错误。
/课程结构
{
123456id: {
..
members: {
uidKey: {
email: some@email.com
},
uidKey2: {
email: another@email.com
}
}
},
some12345string: {
// no members here, so skip
}
}
function.js
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
ref.child('courses/').once('value').then(snap => {
snap.forEach(child => {
var el = child.val();
// check for the 'members' child, skip if absent
if(el.hasOwnProperty('members')) {
// open at the ref and get a snapshot
var membersRef = admin.database().ref('courses/' + child.key + '/members/').once('value').then(childSnap => {
console.log(childSnap.val())
childSnap.forEach(member => {
var email = member.val().email;
console.log(email); // logs fine, but because it's async, after the .then() below for some reason
emails.push(email);
})
})
}
})
return emails // the array
})
.then(emails => {
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 => {
res.send(error)
})
})
})
答案 0 :(得分:1)
以下应该可以解决问题。
正如道格·史蒂文森(Doug Stevenson)在回答中所解释的那样,Promise.all()
方法返回一个单个承诺,当所有承诺由once()
方法返回并推送到promises
数组时,它就会解析,已解决。
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)
});
})
答案 1 :(得分:0)
您应该将诺言放入数组中,并使用Promise.all()
等到它们全部完成,而不是处理内联查询中的所有诺言并将电子邮件推送到数组中。然后,迭代快照数组以构建电子邮件数组。
您可能会发现我的有关在Cloud Functions中使用Promise的教程有助于学习某些技术:https://firebase.google.com/docs/functions/video-series/