Home > OS >  Why can't I redirect to my failure page using node.js?
Why can't I redirect to my failure page using node.js?

Time:06-18

I am working on my newsletter project using Mailchimp API, it works but I can't redirect to a failure page if the status code is not 200, the browser says localhost refused to connect meanwhile success page redirection works great. here's my code:

app.post("/", async(req, res, next)=>{
  const {fName, lName, email} = req.body.user;
  const response = await mailchimp.lists.addListMember("List_ID", {
    email_address: email,
    status: "subscribed",
    merge_fields:{
      FNAME: fName,
      LNAME: lName,
    },
  });
  if(res.statusCode === 200){
    res.sendFile(__dirname   "/success.html");
  }
  else{
    res.sendFile(__dirname   "/failure.html");
  }

});

CodePudding user response:

Maybe you can use "try..catch" to catch unexpected error. See below.

try {
   if(res.statusCode === 200){
      res.sendFile(__dirname   "/success.html");
   }
   else{
     res.sendFile(__dirname   "/failure.html");
   }
} catch (err) {
   res.sendFile(__dirname   "/failure.html");
}

CodePudding user response:

First of all using async with express, if anything in your async function throws express won't get notified about that which would result in an error like:

localhost refused to connect

A quick and dirty solution would be to warp your whole body of the async function into a try .. catch block. But that's tedious and you might still miss some side conditions.

So instead you would want to create a wrapper for that which could look that way: (There are probably better implementations for an express async wrapper)

function asyncExpressWrapper(fn) {
   // return the wrapping middelware be used.
   return async (req, res, next) => {
      try {
         // call the actual middelware you passed
         await fn(req, res, next);
      } catch (err) {
         // will catch any error thrown in fn
         next(err)
      }
   }
}

And use it that way:

app.post("/", asyncExpressWrapper(async(req, res, next) => {
  const {
    fName,
    lName,
    email
  } = req.body.user;

  const response = await mailchimp.lists.addListMember("List_ID", {
    email_address: email,
    status: "subscribed",
    merge_fields: {
      FNAME: fName,
      LNAME: lName,
    },
  });

  if (response.statusCode === 200) {
    res.sendFile(__dirname   "/success.html");
  } else {
    res.sendFile(__dirname   "/failure.html");
  }
}));

Now that will solve the localhost refused to connect problem, and express will tell you which error you didn't handle.

Besides that your res.statusCode === 200 will check the express response statusCode which at that point is always true, if response has a statusCode it has to be response.statusCode === 200.

Now your __dirname "/failure.html" likely still is not shown, as the Promise returned by mailchimp.lists.addListMember likely rejects in the error case. So you needd also a try ... catch in your middleware:

app.post("/", asyncExpressWrapper(async(req, res, next) => {
  const {
    fName,
    lName,
    email
  } = req.body.user;
  
  try {
    const response = await mailchimp.lists.addListMember("List_ID", {
      email_address: email,
      status: "subscribed",
      merge_fields: {
        FNAME: fName,
        LNAME: lName,
      },
    });

    // you probably don't need that if-else at all and only emit 
    // success here, but I don't know mailchimp.lists.addListMember 
    // so that's up to you to figure out. 
    if (response.statusCode === 200) {
      res.sendFile(__dirname   "/success.html");
    } else {
      res.sendFile(__dirname   "/failure.html");
    }
  } catch(err) {
    res.sendFile(__dirname   "/failure.html");
  }
}));
  • Related