#javascript #firebase #google-cloud-functions #nodemailer
# #javascript #огневая база #google-облачные функции #почтовый узел
Вопрос:
Я создал массив объектов в документе, и у каждого объекта есть идентификатор электронной почты.
Я хочу отправить электронное письмо на все эти идентификаторы электронной почты. Итак, я делаю это с помощью Nodemailer в облачной функции, которая запускается при запуске обновления.
Я не могу использовать триггер onCreate, поскольку после создания документа выполняется некоторое обновление, и я не смог получить обновленные изменения.
Итак, я установил mailSent
значение false и хочу изменить его на true при отправке почты.
Но проблема в том, что функция запускается несколько раз, поскольку триггером является обновление документа, и я обновляю документ внутри функции.
Вот мой код функции:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const nodemailer = require("nodemailer");
admin.initializeApp();
const db = admin.firestore();
const mailFrom = functions.config().mail.from;
const mailPwd = functions.config().mail.pwd;
const mailHost = functions.config().mail.host;
const mailPort = functions.config().mail.port;
exports.sendEmailNotification = functions
.region("asia-south1")
.firestore.document("collection/{docId}")
.onUpdate(async (change, _) => {
const updatedData = change.after.data();
const updatedMembersData = updatedData["members"];
const docId = updatedData["id"];
let receiverMail = "";
let partner = "";
updatedMembersData.forEach(async (member) => {
if (!member["mailSent"]) {
receiverName = member["name"];
receiverMail = member["email"];
partner = member["partner"];
let members = [];
let doc = await db
.collection("collection")
.doc(docId)
.get();
let transporter = nodemailer.createTransport({
host: mailHost,
port: mailPort,
auth: {
user: mailFrom,
pass: mailPwd,
},
});
let mailOptions = {
from: "name@example.com",
to: receiverMail,
subject: "EMAIL",
html: `<h2>MAIL TEXT</h2><h4>Hi ${receiverName}, Your partner is ${partner}</h4>`,
};
if (doc.exists) {
const data = doc.data();
members = data["members"];
for (const updateMember of members) {
if (updateMember["name"] === member["name"]) {
updateMember["mailSent"] = true;
}
}
db.collection("collection")
.doc(docId)
.update({ members: members })
.then((_) => {
transporter.sendMail(mailOptions);
return 0;
})
.catch((error) => console.log(error));
} else {
console.log("No such document!");
}
}
});
});
Любая помощь была бы отличной, спасибо!
Комментарии:
1. Вы неправильно работаете с обещаниями. Функция должна возвращать одно обещание, которое выполняется после завершения всей работы aync. Вызов
then
promise не заставляет код приостанавливаться и ждать завершения.2. @DougStevenson Не могли бы вы рассказать, как именно мне это сделать, поскольку я явно не знаю об этом сейчас?
3. Следуя комментарию Дуга, вам следует попробовать использовать
await
indb.collection("collection").doc(docId).update({ members: members })
вместо.then()
. Дайте мне знать, если это сработает.4. @RafaelLemos спасибо за предложение, я попробую это сделать.
5. Хорошо, дайте мне знать, если это исправит проблему.