火力云功能承诺



我很难让承诺链在Firebase云函数中正确流动。它循环遍历 ref 并返回用于发送通知的电子邮件数组。它有一些嵌套的子项,我认为这就是我出错的地方,但我似乎找不到错误。

/课程结构

{
123456id: {
..
members: {
uidKey: {
email: some@email.com
},
uidKey2: {
email: another@email.com
}
}
},
some12345string: {
// no members here, so skip
}
}

功能.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)
})
})
})

下面应该可以解决问题。

正如 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)
});
})

与其处理来自内部查询的所有承诺并将电子邮件推送到数组中,不如将承诺推送到数组中并使用Promise.all()等待它们全部完成。 然后,迭代快照数组以构建电子邮件数组。

您可能会发现我关于在云函数中使用承诺的教程有助于学习一些技术: https://firebase.google.com/docs/functions/video-series/

最新更新