Как отправить несколько электронных писем при запуске обновления документа с помощью облачной функции?

#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 in db.collection("collection").doc(docId).update({ members: members }) вместо .then() . Дайте мне знать, если это сработает.

4. @RafaelLemos спасибо за предложение, я попробую это сделать.

5. Хорошо, дайте мне знать, если это исправит проблему.