If statement running after function being called

Slappe

New Member
#1
I'm setting up a mailer to send an email to the relevant recipient about some details of an appointment request.

I'm having an issue where the IF statement that runs to decide who the necessary recipient should be is running after the email transporter and is giving me an error saying that no recipient has been defined.

Here is the code
Mã:
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);
})
In the Firebase logs, I am getting these errors

1bMQL.png

It's showing that the IF statement is being run after the transporter function causing it to error.

I've tried all manor of things but cant seem to get it to play ball!

Help is appreciated, cheers!
 

Admin

Administrator
Thành viên BQT
#2
Pulling data from your database is async, your current code ignores that and tries to continue before the promise has resolved.

This is quite a common error when people aren't used to promises. Promises are basically pretty callbacks, instead of (err, info) you get a function of .then and .catch (and a few others).

You need to put your email code inside the .then function. So it'll become something like this:

Mã:
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 = toEmail;

          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);
            });
          });
    });
  }
}
I've done three things here.

  1. I've wrapped everything in a function for ease.
  2. I've moved the email sending code into the promise .then function. This means once something is fetched from the database you're sending the email, so you're now waiting for the response.
  3. I've wrapped the transporter.sendMail in a function. There are utilities for doing this but for clarity I've shown you how to do this by hand. This means the new function from point 1 now returns a promise. You can now use the top function sendMail the same way you've done your database code, by calling sendMail().then(result...).catch(error...).
It's often more idiomatic to not mix callback and promise code by wrapping up any callback oriented code with things like Bluebird.promisify, or wrapping up a callback oriented function by hand the way I have. This means you're just dealing with .then and .catch type code.

I apologies if you already knew about Promises vs Callbacks, it's just a common theme I see on questions so I've answered it in full.
 

Từ khóa phổ biến

You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an alternative browser.

Chủ Đề Xem Nhiều

Top