Cloud Functions for Firebase onWrite 触发器:snapshot.val 不是函数 [英] Cloud Functions for Firebase onWrite trigger: snapshot.val is not a function
问题描述
我在同一个 index.js 文件中创建了几个函数,即 sendEmail
、sendEmailByDbStatusChange
和 sendEmailConfirmation
.
I created few functions in the same index.js file, which is sendEmail
, sendEmailByDbStatusChange
and sendEmailConfirmation
.
sendEmail
- 通过 HTTP/API 调用
sendEmail
- To be call via HTTP/API
sendEmailByDbStatusChange
- 在值更改时监听 DB,但操作是硬编码的
sendEmailByDbStatusChange
- listening to DB while value change, but the action is hardcoded
sendEmailConfirmation
- 在值更改时列出到 DB,操作以快照为准.
sendEmailConfirmation
- Listing to DB while value change, the action subject to the snapshot.
以下是我的代码:
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 函数后,控制台显示 sendEmailConfirmation
由于 event2.val
不是函数而无法顺利执行.
My problem is, after i deploy the code to firebase function, the console shows that the sendEmailConfirmation
unable to execute smoothly due to event2.val
is not a function.
我当前的代码结合了我的自定义代码和原始代码,其中 sendEmailConfirmation
是原始代码.当独立运行原始代码时,它确实有效(原始代码是 event
而不是 event2
用于快照).
My current code combined with my customize code and the original code, which sendEmailConfirmation
is the original code. When run the original code independently it did work (original was event
instead of event2
for the snapshot).
请指教.
推荐答案
您似乎已更新到 Firebase SDK for Cloud Functions v1.0,但没有升级您的代码以匹配.
It looks like you updated to v1.0 of the Firebase SDK for Cloud Functions, but didn't upgrade your code to match.
此文档页面中解释了整个过程.现在您正受到数据库触发器更改,这表明:
The entire process is explained in this documentation page. Right now you're being hit by the changes in database triggers, which shows that:
在早期版本中,event.data
是 DeltaSnapshot
;现在在 v 1.0 中,它是一个 DataSnapshot
.
Event data now a DataSnapshot
In earlier releases,
event.data
was aDeltaSnapshot
; now in v 1.0 it is aDataSnapshot
.
对于onWrite
和onUpdate
事件,data
参数有before
和after
字段.其中每一个都是一个 DataSnapshot
,其方法与 admin.database.DataSnapshot
中可用的方法相同.例如:
For onWrite
and onUpdate
events, the data
parameter has before
and after
fields. Each of these is a DataSnapshot
with the same methods available in admin.database.DataSnapshot
. For example:
之前 (<= 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
});
根据该示例,您将需要以下内容:
According to that example, you'll need something along these lines:
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));
});
这篇关于Cloud Functions for Firebase onWrite 触发器:snapshot.val 不是函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!