简体   繁体   中英

how to use asynchronous and synchronous programming in right time

I am new in asynchronous programming in javascript. I have two email provider sendgrid and mailgun. i want to send email with one of this then if any error happened, resend email with another one. finally if email sent successfully save into db and response with json object. here is my code :

  if(req.query.provider== 'mailgun'){

      console.log('sending with mailgun ...');
      mailgun.messages().send(data, function (err, res) {
      if(err){
          fail = true;
          console.log(`error in sending email with mailgun. error :${err}`)
        } else {
          console.log('email sent with mailgun')
          fail = false;
        }
      });

    }else if(req.query.provider == 'sendgrid'){
      console.log('sending emial with sendgrid')
      sendgrid.sendMail(data, function(err, res) {
         if (err) {
               console.log(`error in sending with sendgrid. error: ${err} + response : ${res}`)
           fail = true
            }
             console.log(`email sent with sendgrid`)
           fail = false
         });
       }

       if(fail){
         if(req.query.provider == 'mailgun'){
           console.log('sending with sendgrid ...')
           sendgrid.sendMail(data, function(err, res){
             if(err){
               console.log(`error: ${err} + response : ${res}`)

             }else {
               console.log(`response: ${res}`)
               fail = false
             }
           })

         }else if(req.query.provider == 'sendgrid'){
            console.log('sendging with mailgun')
            mailgun.messages().send(data, function (err, res) {
              if(err){
              console.log(`error: ${err} + response : ${res}`)
            }else{
              console.log(`response: ${res}`)
              fail = false
            }
            })
         }
       }

  if(!fail){
      db.models.Email.create(req.query, (err, result)=>{
        if(err){
          handleErrors(res, err);
          console.log(`error in creating Email :${err}`)
        }else {
          console.log()
          res.json(result)
        }
      });
    } else {
          console.log('fail in sending error');
          res.json('sorry.');
        }
      });

the problem here is, this code run asynchronously. for example, it sent with mailgun then jump to fail check and send again with sendgrid. doesn't wait for the response of sending. how can I fix and improve this ? should I use async', await'?

Here an example using async/await pattern

(It can be improved to support generically multiple mailer, you have to adapt the part where you select the alternativeMailerName) .

  /**
   * Send an email using a given mailer
   *
   * return true if success, false otherwise
   */
  async sendMailUsingMessages(mailerName, data) {
    const {
      mailer,
      func,
    } = [
      {
        mailer: 'mailgun',
        func: async () => mailgun.messages().send(data);
      },
      {
        mailer: 'sendgrid',
        func: async () => sendgrid.sendMail(data);
      },
    ].find(x => x.mailer === mailerName);

    console.log(`sending with ${mailer} ...`);

    try {
      const res = await func();

      console.log(`email sent with ${mailer}`);

      return true;
    } catch (err) {
      console.log(`error in sending email with ${mailer}. error :${err}`)

      return false;
    }
  }

  /**
   * Send an email
   */
  async sendEmail(req, res, data) {
    if (!(await sendMailUsingMessages(req.query.provider, data))) {
      // One fail, so we try the other one
      const alternativeMailerName = req.query.provider === 'mailgun' ? 'sendgrid' : 'mailgun';

      if (!(await sendMailUsingMessages(alternativeMailerName, data))) {
        // Double fail
        console.log('fail in sending error');

        res.json('sorry.');

        return;
      }
    }

    // Success
    try {
      const result = await db.models.Email.create(req.query);

      res.json(result);
    } catch (err) {
      handleErrors(res, err);

      console.log(`error in creating Email :${err}`)
    }
  }

You can try deferred and promise execution of JavaScript. Please the first example below without deferred and promise. After that, you can find how easy it is with deferred and promise execution,

 var firstData = null; var secondData = null; var responseCallback = function () { if (!firstData || !secondData) return; // do something } $.get("http://example.com/first", function (data) { firstData = data; responseCallback(); }); $.get("http://example.com/second", function (data) { secondData = data; responseCallback(); }) 

Then the same with deferred and promise,

 var firstPromise = $.get("http://example.com/first"); var secondPromise = $.get("http://example.com/second"); $.when(firstPromise, secondPromise).done(function (firstData, secondData) { // do something }); 

You can read more here https://davidwalsh.name/write-javascript-promises

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM