3

I'd like to know the best way to deal with errors in a response - request. I have this route that receive a request:

app.get('/getInfo', function (req, res, next) {
    let obj = {}
    try {
        obj = { 
            ...                
            date: lastUpdatedDate('./utils/appVersion.js'),
            ...
        }
        res.status(200).send(obj)
    } catch (error) {
        console.log(error.message)
        res.send({error: "The data wasn't load"})
    }       
})

And this function where the request is made

getInfo () {
    axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
        this.appInfoHandler(resp.data)
      })
      .catch(function (error) {    
        console.log(error)
      })
  }

What's the best way to deal with the error if it occurs in the server side? Let's supose that in this code block the directory doesn't exists: lastUpdatedDate('./directoreyDoesntExists/appVersion.js'),

So my code goes to the catch block.

Should I send the error like this:

res.send({error: "The data wasn't load"})

Should I set a status like this?

  res.status(500).send({error: "The data wasn't load"})

Or should I set a status with a different status code?

Based on that, what's the best way to deal with it in my frontend method getInfo() to get the error and show the error message on web interface?

Should I do an if else inside the .then block like this?

 getInfo () {
      axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
            if(resp.status === 200){
                 this.appInfoHandler(resp.data)
            }else if (resp.status === 400){
                  //print error message on web interface
            }else if (resp.status === 500){
                  //print error message on web interface
          })
          .catch(function (error) {    
            console.log(error)
          })

Or should I deal with this error directly in the catch block like this

getInfo () {
    axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
        this.appInfoHandler(resp.data)
      })
      .catch(function (error) {    
        //print error message on web interface
      })
  }
mr.abdo
  • 445
  • 1
  • 5
  • 15

4 Answers4

4

For this case

res.send({error: "The data wasn't load"}) 

vs

res.status(500).send({error: "The data wasn't load"})

send a status is just more detailed, but both are ok. check Proper way to set response status and JSON content

For this case, depends on what you need

then(resp => {
            if(resp.status === 200){
                 this.appInfoHandler(resp.data)
            }else if (resp.status === 400){
                  //print error message on web interface
            }else if (resp.status === 500){
                  //print error message on web interface
          })
          .catch(function (error) {    
            console.log(error)
          })

vs

getInfo () {
    axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
        this.appInfoHandler(resp.data)
      })
      .catch(function (error) {    
        //print error message on web interface
      })
  }

You can handle all the errors sending them to the catch block

else if (resp.status === 400){
                  //print error message on web interface

not printing the error in here but throwing a new error that will be send it to the catch block

throw new ApiError("UserNotFount",400,"not found");
throw new Error('Error 400, not found');
Juan Velasquez
  • 385
  • 4
  • 15
  • I did a couple of tests, and when I send a response in the server side like this `res.status(500).send({error: "The data wasn't load"})`, It goes to catch block in the frontend side. So, should send it with status 200? – mr.abdo just now Edit – mr.abdo Jun 26 '19 at 12:45
  • 1
    No, the catch is only to handle the errors, you shouldn't send a 200 in a catch, if you don't want your app to stop don't send a 500, you can use something like throw new Error('The data wasn't load'); – Juan Velasquez Jun 26 '19 at 12:50
3

For this case

res.send({error: "The data wasn't load"}) 

vs

res.status(500).send({error: "The data wasn't load"})

I would suggest sending error as well as status code because that will be more descriptive for the client.

and for the second case

getInfo () {
      axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
            if(resp.status === 200){
                 this.appInfoHandler(resp.data)
            }else if (resp.status === 400){
                  //print error message on web interface
            }else if (resp.status === 500){
                  //print error message on web interface
          })
          .catch(function (error) {    
            console.log(error)
          })

vs

getInfo () {
    axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
        this.appInfoHandler(resp.data)
      })
      .catch(function (error) {    
        //print error message on web interface
      })
  }

In this case I would suggest to use the catch block directly whenever you get an error because response status depends on error but not the other way around

Sanjay
  • 81
  • 11
3

As a beginner working on a REST Api, you should take a look at a guidelines - microsoft's are pretty legit: https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design.

Basically, you need to return the correct HTTP code for each request, take a look at https://http.cat/ - for example if the request is malformed, return 400, and if the user is unauthorized return 401:

if (!req.body.name) {
  res.status(400).send({ error: 'missing user name' }); // 400 bad request
}
const user = getUser(req.body.name, req.body.pass);

if(!user) {
  res.status(401).send({ error: 'user does not exist' }); // 401 unauthorized
}

try {
  const token = createToken(user);
  // better to set a cookie
  res.status(200).send({ token }); // 200 success
} catch(e) {
  res.status(500).send({ erroe: e.message }); // 500 internal error
}

if(isTeapot) {
  res.status(418).send({ error: 'I can only make tea' }); // 418 teapot, totally real
}

To make things easier there are a lot of libraries to help you generate better error messages and handle errors better, one of my favorites is celebrate

Liron Navon
  • 1,068
  • 1
  • 11
  • 22
  • 1
    Tku so much. U response is helping a lot. Sending a message like this `res.status(500).send({error: 'I can only make tea' })`, whats the best way to show this message on the client side? If I do somenthing like that `console.log(error)` inside the catch block, this message is not showed. – mr.abdo Jun 26 '19 at 13:16
  • 1
    That's your decision how you show it, each company does so in a different way, for example, Microsoft just shows a loader on azure (damn microsoft!), some sites will only output to the log since they are lazy, and some show a snackbar or a toast or some modal with information - depends on the issue and your frontend culture. – Liron Navon Jun 27 '19 at 14:27
2

Any status code other that 200 would mean unsuccessful so you dont need to use those if-else statements. The better alternative is to catch the error and send it with response as it is. The benefit is that you would receive the type of error occured without hardcoding the status codes. (for ex, we take the status code here to be 400 unsuccessful)

 .catch(function (error) {    
        //print error message on web interface
        res.status(400).send(JSON.stringify(error, undefined, 2));
      });

By using the stringify method you can print the exact error on the console also.

.catch(function (error) {    
            console.log(JSON.stringify(error, undefined, 2));
          });

The parameters in the stringify method here are:

  1. error object

  2. undefined: The array which contains the keys for filtering the keys in the object(here, error). All those keys present in this array are only the ones not filtered out.

  3. 2: It is used to introduce whitespace in object representation

Harsh Mandalgi
  • 204
  • 2
  • 5
  • Perfect. I got it. Let's supose that I want to send a specif error message, ex. "The data wasn't load". What's the best way to do it? Should I do it on server side? – mr.abdo Jun 26 '19 at 13:01
  • 1
    Depends on your usecase. If you dont want to show the error to the user of API, you can always print a sweet "Ooh! Something broke. We are on it!" message. If you want to show the user then you can use stringify in both places. While testing I would recomment to show error on both sides - server and API user. – Harsh Mandalgi Jun 26 '19 at 13:04
  • 1
    Yes, the data didn't load message on the server side would be a good idea to start with. – Harsh Mandalgi Jun 26 '19 at 13:46