调用函数后的 if 语句 运行

If statement running after function being called

我正在设置一个邮件程序,以向相关收件人发送有关预约请求的一些详细信息的电子邮件。

我遇到一个问题,运行决定谁是必要的收件人的 IF 语句在电子邮件传输器之后 运行ning 并且给我一个错误说不收件人已定义。

这是代码

let recipientEmail;

if (careHome === 'ACareHome') {
    admin.database().ref('managers').once("value").then((snapshot) => {
        let managerEmail = snapshot.child("Manager Name").val();
        recipientEmail = managerEmail;
        console.log(`Recipient is ${recipientEmail}`);
   });
}

const mailOptions = {
    from: '*****', // sender address
    subject: `An appointment has been requested at ${ACareHome}.`,
    html: `Hello, an appointment has been booked at ${ACareHome} on ${date} at ${time}. The requestors name is, ${firstName}. You can email them on ${email}.` 
};

mailOptions.to = recipientEmail;

transporter.sendMail(mailOptions, function(error, info){
    if(error){
        return console.log(error);
    }
    console.log('Message sent: ' + info.response);
})

在 Firebase 日志中,我收到了这些错误

这表明 IF 语句在传输函数之后 运行 导致它出错。

我尝试了所有方法,但似乎无法让它打球!

感谢帮助,干杯!

从您的数据库中提取数据是异步的,您当前的代码会忽略它并尝试在承诺解决之前继续。

当人们不习惯承诺时,这是一个很常见的错误。承诺基本上是漂亮的回调,而不是 (err, info) 你得到 .then.catch(以及其他一些)的函数。

您需要将电子邮件代码放入 .then 函数中。所以它会变成这样:

function sendEmail() {
    let recipientEmail;

    if (careHome === 'ACareHome') {
        admin.database().ref('managers').once("value").then((snapshot) => {
            let managerEmail = snapshot.child("Manager Name").val();
            recipientEmail = managerEmail;
            console.log(`Recipient is ${recipientEmail}`);

            const mailOptions = {
                from: '*****', // sender address
                subject: `An appointment has been requested at ${ACareHome}.`,
                html: `Hello, an appointment has been booked at ${ACareHome} on ${date} at ${time}. The requestors name is, ${firstName}. You can email them on ${email}.` 
            };

            mailOptions.to = recipientEmail;

            return new Promise(function promise(resolve, reject) {
                transporter.sendMail(mailOptions, function(error, info){
                    if (error) {
                        return console.log(error);
                        return reject(error);
                    }
                    console.log('Message sent: ' + info.response);
                    return resolve(info);
                });
            });
        });
    } 
}

我在这里做了三件事。

  1. 为了方便起见,我将所有内容都封装在一个函数中。
  2. 我已将电子邮件发送代码移至 promise .then 函数中。这意味着一旦从数据库中提取了一些内容,您就可以发送电子邮件,因此您现在正在等待回复。
  3. 我已经将 transporter.sendMail 包装在一个函数中。有用于执行此操作的实用程序,但为了清楚起见,我向您展示了如何手动执行此操作。这意味着第 1 点的新功能现在 returns 是一个承诺。您现在可以像完成数据库代码一样使用顶部函数 sendMail,方法是调用 sendMail().then(result...).catch(error...).

通过用 Bluebird.promisify 之类的东西包装任何面向回调的代码,或者像我那样手动包装面向回调的函数,不混合回调和承诺代码通常更为惯用。这意味着您只是在处理 .then.catch 类型代码。

如果您已经了解 Promises 与 Callbacks,我深表歉意,这只是我在问题中看到的一个常见主题,所以我已经完整地回答了它。