Skip to content

Instantly share code, notes, and snippets.

@mjurincic
Forked from slavafomin/nodejs-custom-es6-errors.md
Last active November 20, 2019 15:55
Show Gist options
  • Save mjurincic/297a6aa8913f06e5e15297baa1ef5e09 to your computer and use it in GitHub Desktop.
Save mjurincic/297a6aa8913f06e5e15297baa1ef5e09 to your computer and use it in GitHub Desktop.
Custom ES6 errors in Node.js

Here's how you could create custom error classes in Node.js using latest ES6 / ES2015 syntax.

I've tried to make it as lean and unobtrusive as possible.

Defining our own base class for errors

errors/ApplicationError.js

class ApplicationError extends Error {
  get name() {
    return this.constructor.name;
  }
}
  
class DatabaseError extends ApplicationError {}
class UserFacingError extends ApplicationError {}
  
module.exports = {
  ApplicationError,
  DatabaseError,
  UserFacingError
}  

errors/HttpError.js

const { UserFacingError } = require('./applicationError')
class BadRequestError extends UserFacingError {
  get statusCode() {
    return 400;
  }
}

class NotFoundError extends UserFacingError {
  get statusCode() {
    return 404;
  }
}

module.exports = {
  BadRequestError,
  NotFoundError
}  

errors/AppError.js

module.exports = class AppError extends Error {
  constructor (message, status) {
  
    // Calling parent constructor of base Error class.
    super(message);
    
    // Saving class name in the property of our custom error as a shortcut.
    this.name = this.constructor.name;

    // Capturing stack trace, excluding constructor call from it.
    Error.captureStackTrace(this, this.constructor);
    
    // You can use any additional properties you want.
    // I'm going to use preferred HTTP status for this error types.
    // `500` is the default value if not specified.
    this.status = status || 500;
    
  }
};

Defining specific error types

errors/EmailTakenError.js

module.exports = class EmailTakenError extends require('./errors/AppError') {
  constructor (message) {
    // Providing default message and overriding status code.
    super(message || 'Specified E-Mail is already taken', 400);
  }
};

errors/RequestValidationError.js

module.exports = class extends require('./AppError') {
  constructor (fields) {
    // Overriding both message and status code.
    super('Request validation failed', 400);
    // Saving custom property.
    this.fields = fields || {};
  }
};

Throwing and catching

const AppError = require('./../api/errors/AppError');
const EmailTakenError = require('./../api/errors/EmailTakenError');
const RequestValidationError = require('./../api/errors/RequestValidationError');


try {
  // Throwing EmailTakenError exception.
  throw new EmailTakenError();
} catch (error) {
  // Catching exception by class.
  if (error instanceof EmailTakenError) {
    console.log('E-Mail validation failed!', error);
  } else {
    // If failed to catch, throwing it higher.
    console.log('Unknown error', error);
    throw error;
  }
}


try {
  // Throwing RequestValidationError exception.
  throw new RequestValidationError();
} catch (error) {
  // Catching error by base (parent) class.
  if (error instanceof AppError) {
    console.log('Some application error occurred!', error);
  } else {
    console.log('Unknown error', error);
    throw error;
  }
}

Feedback

It works great for my application, however cirtisim is welcomed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment