MasterX
MasterX

Reputation: 91

Foreach loop not getting completed

I'm using Node js, nodemailer and firebase functions in my application.

I've a list of emails in an array emailConfig

const emailConfig = [
  {
    "name": "A",
    "Email": "[email protected]"
  },
  {
    "name": "B",
    "Email": "[email protected]"
  }
];

So I need to send an email to all in emailConfig.

So I'm doing this,

function sendMail() {
  emailConfig.forEach(email => {
    const mailOptions = {
      from: '[email protected]',
      to: email.Email,
      subject: 'Sending Email using Node.js',
      text: `That was easy! ${email.name}`,
      attachments: [
        {
          filename: `${email.name}_KeyMetrics.xlsx`,
          path: `${tempath}/${email.name}_KeyMetrics.xlsx`
        },
        {
          filename: `${email.name}_MandatoryCourses.xlsx`,
          path: `${tempath}/${email.name}_MandatoryCourses.xlsx`
        },
      ]
    };
    return transporter.sendMail(mailOptions, (erro, info) => {
      if (erro) {
        return res.send(erro.toString());
      }
      return res.send('Sended');
    });
  });
}

I'm calling the sendMail() on request.

Issue is, I'm getting multiple emails and finally error in terminal Error: Function timed out.

sendMail() is not getting finished. What i'm doing wrong here ?

Upvotes: 0

Views: 64

Answers (2)

Yone
Yone

Reputation: 976

  1. you cannot call send() after its first call on the single response (assuming your res is a Response socket).
  2. Array.forEach is synchronous, your callbacks will no be handled properly.

Upvotes: 2

Function in forEach is does not return any result. So since you call return keyword, your thread stop at there. Try to remove return keyword like this:

function sendMail() {
  emailConfig.forEach(email => {
    const mailOptions = {
      from: '[email protected]',
      to: email.Email,
      subject: 'Sending Email using Node.js',
      text: `That was easy! ${email.name}`,
      attachments: [
        {
          filename: `${email.name}_KeyMetrics.xlsx`,
          path: `${tempath}/${email.name}_KeyMetrics.xlsx`
        },
        {
          filename: `${email.name}_MandatoryCourses.xlsx`,
          path: `${tempath}/${email.name}_MandatoryCourses.xlsx`
        },
      ]
    };
    //remove return below
    transporter.sendMail(mailOptions, (erro, info) => {
      if (erro) {
        return res.send(erro.toString());
      }
      return res.send('Sended');
    });
  });
}

Or if you need an array of result. Try .map() prototype instead:

function sendMail() {
  emailConfig.map(email => { //replace forEach by map
    const mailOptions = {
      from: '[email protected]',
      to: email.Email,
      subject: 'Sending Email using Node.js',
      text: `That was easy! ${email.name}`,
      attachments: [
        {
          filename: `${email.name}_KeyMetrics.xlsx`,
          path: `${tempath}/${email.name}_KeyMetrics.xlsx`
        },
        {
          filename: `${email.name}_MandatoryCourses.xlsx`,
          path: `${tempath}/${email.name}_MandatoryCourses.xlsx`
        },
      ]
    };
    return transporter.sendMail(mailOptions, (erro, info) => {
      if (erro) {
        return res.send(erro.toString());
      }
      return res.send('Sended');
    });
  });
}

Upvotes: -1

Related Questions