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

Firebase onWrite触发器的云函数:快照。val不是一个函数

  •  5
  • Jerry  · 技术社区  · 7 年前

    我在同一索引中创建了几个函数。js文件,即 sendEmail ,则, sendEmailByDbStatusChange sendEmailConfirmation

    发送电子邮件 -通过HTTP/API进行调用

    通过数据库状态更改发送电子邮件 -在值更改时侦听DB,但操作是硬编码的

    发送电子邮件确认 -当值更改时,将列表显示到DB,操作以快照为准。

    以下是我的代码:

    const functions = require('firebase-functions');
    const nodemailer = require('nodemailer');
    const gmailEmail = functions.config().gmail.email;
    const gmailPassword = functions.config().gmail.password;
    const mailTransport = nodemailer.createTransport({
      service: 'gmail',
      auth: {
        user: gmailEmail,
        pass: gmailPassword,
      },
    });
    
    // Sends an email confirmation when a user changes his mailing list subscription.
    exports.sendEmail = functions.https.onRequest((req, res) => {
      if (req.body.subject === undefined || req.body.recipient === undefined) {
        // This is an error case, as "message" is required.
        //res.status(400).send('subject/body/recipient is missing!');
        return false
      } else {
        const mailSubject = req.body.subject;
        const mailHtmlBody = req.body.htmlBody;
        const mailRecipient = req.body.recipient;
    
    
    
        const mailOptions = {
          from: '"Food Ninja." <foodninjaapp@gmail.com>',
          to: mailRecipient,
          subject: mailSubject,
          html: mailHtmlBody
        };
    
        //res.status(200).send('Success: ' + mailSubject + ' to ' + mailRecipient);
    
        return mailTransport.sendMail(mailOptions)
          .then(() => {
            console.log(`${mailSubject}subscription confirmation email sent to: `, mailRecipient)
            return res.status(200).send('Success: ' + mailSubject + ' to ' + mailRecipient)
          })
          .catch((error) => console.error('There was an error while sending the email:', error));
      }
    });
    
    exports.sendEmailByDbStatusChange = functions.database.ref('/users/{uid}').onWrite((event) => {
      //const snapshot = event.data;
      //const val = snapshot.val();
    
      //if (!snapshot.changed('subscribedToMailingList')) {
      //  return null;
      //}
    
      const mailSubject = 'Sending email with Cloud Function - by DB onWrite Trigger';
      const mailHtmlBody = '<h1>Hello Jerry</h1><p>If you receiving this means that you have successfully deployed a customized firebase function</p><p>Be Happy!<br><br>Food Ninja Team</p>';
      const mailRecipient = 'admin@phd.com.my';
    
      const mailOptions = {
        from: '"Food Ninja." <foodninjaapp@gmail.com>',
        to: mailRecipient,
        subject: mailSubject,
        html: mailHtmlBody
      };
    
      //const subscribed = val.subscribedToMailingList;
    
      // Building Email message.
      //mailOptions.subject = subscribed ? 'Thanks and Welcome!' : 'Sad to see you go :`(';
      //mailOptions.text = subscribed ? 'Thanks you for subscribing to our newsletter. You will receive our next weekly newsletter.' : 'I hereby confirm that I will stop sending you the newsletter.';
    
      return mailTransport.sendMail(mailOptions)
        .then(() =>
          console.log(`${mailSubject}subscription confirmation email sent to: `, mailRecipient)
          //return res.status(200).send('Success: ' + mailSubject + ' to ' + mailRecipient)
        )
        .catch((error) => console.error('There was an error while sending the email:', error));
    });
    
    exports.sendEmailConfirmation = functions.database.ref('/users/{uid}').onWrite((event2) => {
      console.log(event2)
      console.log(event2.val())
      console.log(event2.val().data)
      console.log(event2.data)
      console.log(event2.data.val())
      const snapshot = event2.data;
      console.log(snapshot)
      const val = snapshot.val();
      console.log(val)
    
      if (!snapshot.changed('subscribedToMailingList')) {
        return null;
      }
    
      const mailOptions = {
        from: '"Spammy Corp." <noreply@firebase.com>',
        to: val.email,
      };
    
      const subscribed = val.subscribedToMailingList;
    
      // Building Email message.
      mailOptions.subject = subscribed ? 'Thanks and Welcome!' : 'Sad to see you go :`(';
      mailOptions.text = subscribed ? 'Thanks you for subscribing to our newsletter. You will receive our next weekly newsletter.' : 'I hereby confirm that I will stop sending you the newsletter.';
    
      return mailTransport.sendMail(mailOptions)
        .then(() => console.log(`New ${subscribed ? '' : 'un'}subscription confirmation email sent to:`, val.email))
        .catch((error) => console.error('There was an error while sending the email:', error));
    });
    

    我的问题是,在我将代码部署到firebase函数后,控制台显示 发送电子邮件确认 由于以下原因无法顺利执行 event2.val 不是函数。

    我的当前代码与我的自定义代码和原始代码相结合 发送电子邮件确认 是原始代码。当独立运行原始代码时,它可以工作(原始代码是 event 而不是 event2 对于快照)。

    请告知。

    2 回复  |  直到 7 年前
        1
  •  15
  •   Frank van Puffelen    7 年前

    看起来您已更新到v1。用于云功能的Firebase SDK的0,但未升级您的代码以匹配。

    有关整个过程的说明,请参见 this documentation page .现在你被 changes in database triggers ,这表明:

    事件数据现在是DataSnapshot

    在早期版本中, event.data 是一个 DeltaSnapshot ;现在在1.0版中 DataSnapshot

    对于 onWrite onUpdate 事件 data 参数具有 before after 字段。每一个都是 数据快照 使用中可用的相同方法 admin.database.DataSnapshot .例如:

    之前(<=v0.9.1)

    exports.dbWrite = functions.database.ref('/path').onWrite((event) => {
      const beforeData = event.data.previous.val(); // data before the write
      const afterData = event.data.val(); // data after the write
    });
    

    现在(v1.0.0)

    exports.dbWrite = functions.database.ref('/path').onWrite((change, context) => {
      const beforeData = change.before.val(); // data before the write
      const afterData = change.after.val(); // data after the write
    });
    

    根据该示例,您将需要以下内容:

    exports.sendEmailConfirmation = functions.database.ref('/users/{uid}').onWrite((change, context) => {
      const snapshot = change.after;
      const val = snapshot.val();
      console.log(val)
    
      if (!snapshot.changed('subscribedToMailingList')) {
        return null;
      }
    
      const mailOptions = {
        from: '"Spammy Corp." <noreply@firebase.com>',
        to: val.email,
      };
    
      const subscribed = val.subscribedToMailingList;
    
      // Building Email message.
      mailOptions.subject = subscribed ? 'Thanks and Welcome!' : 'Sad to see you go :`(';
      mailOptions.text = subscribed ? 'Thanks you for subscribing to our newsletter. You will receive our next weekly newsletter.' : 'I hereby confirm that I will stop sending you the newsletter.';
    
      return mailTransport.sendMail(mailOptions)
        .then(() => console.log(`New ${subscribed ? '' : 'un'}subscription confirmation email sent to:`, val.email))
        .catch((error) => console.error('There was an error while sending the email:', error));
    });
    
        2
  •  2
  •   Doug Stevenson    7 年前

    自firebase功能模块1.0.0版起,数据库 onWrite 活动现在提供 Change 对象而不是 DataSnapshot 对象作为第一个参数。您可以在 documentation 。您应该使用此更改对象来选择是在调用数据库的更改之前还是之后检查数据库的内容。