Ozan Ertürk
Ozan Ertürk

Reputation: 485

Node.js exception handler, Designating error if its validation error

I am a newbie in the node.js environment. I used to code dotNet and I am trying to get used to node.js.

Projects that I made in MVC .net, I was using middleware for exception handler and if a validation error occurs I was throwing CustomException which has a property describes the error is validation error or not.

I am trying to do this strategy in express.js. I use express-validator

router.post("/register", validators, (req, res) => {

    validationResult(req).throw();

    var userDto = req.dto;
    userService.registerUser(userDto)
        .then(result => {
            res.status(200).send("User Created Succesfully");
        }).
        catch(err => {
            //log it,
            res.status(500).send("");
        })
})

if error occurs experss-validator throws an error with 'Validation failed' message

global error handler like

app.use((err,req,res,nex)=>{
    if(err.message ==='Validation failed'){
        console.log(err);
        res.status(422).send(err.array());
    }
    console.log(err);

});

As you see in the error handler, I tried to understand if the error is validation error or not by control the error message. It seems ugly, isn't it?

In general, I have not seen this approach in node.js. Could it be the abstraction of single responsibility or something else? It seems node.js tries to keep simple Error stuff. I am suffering that lack of this mechanism. Maybe I am doing anti-pattern but I could not figure it out. If you have a better approach I will immediately give up mine :)

Thanks.

Upvotes: 1

Views: 2873

Answers (3)

userrj_vj_051620
userrj_vj_051620

Reputation: 201

We can create custom errors in Javascript, by using the extend the Error class

For example:

    class ValidationError extends Error {
      constructor(message) {
        super();
        Error.captureStackTrace(this, this.constructor);
        this.name = this.constructor.name;
        this.message = message;
      }
    }
    
    class NotFoundError extends Error {
      constructor(message) {
        super();
        Error.captureStackTrace(this, this.constructor);
        this.name = this.constructor.name;
        this.message = message;
        this.code = 404;
    
      }
    }

Upvotes: 0

Cisco
Cisco

Reputation: 22952

In general yes, errors are usually simple in the Node.js world. Unlike C#, you'll typically only see one exception/error type: Error.

You are free to create your own error objects (using ES2015 classes syntax):

class MyError extends Error {
  constructor(message) {
    super(message);
  }
}

Which then you can check the type as you would in C#:

const myError = new MyError();
console.log(myError instanceof MyError)

However, you don't typically see projects/persons create their own errors. What typically happens is they'll just use the standard Error object as is with a specific error message, which you are checking above. However, you are free to add on extra properties (some do this) to help distinguish between Error objects:

const stdError = new Error()
std.myCustomProperty = 'whoohoo'

It is good practice to utilize error middleware which you are doing to handle errors.

I have a sample MVC style Express project you can look at for a better (IMO) way to handle errors: https://github.com/ciscoo/evaluacion


Edit: As of Node.js v10.0.0, all Error objects will have a code property.

Upvotes: 1

E Compton
E Compton

Reputation: 34

You want to catch any validation errors at the controller level, the global error handler is for catching anything your controllers might miss (e.g. 404s).

router.post('/register', validators, (req, res) => {

  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).json({ errors: errors.mapped() });
  }

  var userDto = req.dto;
  userService.registerUser(userDto)
    .then(result => {
      res.status(200).send("User Created Succesfully");
    }).
    catch(err => {
      //log it,
      res.status(500).send("");
  });
});

or alternatively with the throw syntax:

router.post('/register', validators, (req, res) => {

  try {
    validationResult(req).throw();
  } catch (errors) {
    return res.status(422).json({ errors: errors.mapped() });
  }

  var userDto = req.dto;
  userService.registerUser(userDto)
    .then(result => {
      res.status(200).send("User Created Succesfully");
    }).
    catch(err => {
      //log it,
      res.status(500).send("");
  });
});

Upvotes: 0

Related Questions