代码之家  ›  专栏  ›  技术社区  ›  Brian

Firebase云功能承诺

  •  0
  • Brian  · 技术社区  · 8 年前

    我很难让承诺链在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)
        })
      })
    })
    
    2 回复  |  直到 8 年前
        1
  •  1
  •   Renaud Tarnec    8 年前

    下面的技巧应该可以做到。

    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)
      });
    
    })
    
        2
  •  0
  •   Doug Stevenson    8 年前

    不要处理来自内联查询的所有承诺并将电子邮件推送到数组中,而应该将承诺推送到数组中并使用 Promise.all() 等到一切都结束。然后,迭代快照数组以构建电子邮件数组。

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