首页 文章

Firebase Cloud 功能承诺

提问于
浏览
0

我很难让一个承诺链在firebase Cloud 功能中正确流动 . 它循环遍历ref并返回一组电子邮件以发送通知 . 它有一些嵌套的孩子,我认为这是我出错的地方,但我似乎无法找到错误 .

/courses structure

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

2 回答

  • 1

    以下应该可以解决问题 .

    正如Doug Stevenson在他的回答中所解释的那样, Promise.all() 方法返回一个单一的promise,当 once() 方法返回并推送到 promises 数组的所有promise都已解决时,它会解析 .

    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)
      });
    
    })
    
  • 0

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

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

相关问题