How to handle errors in async Express?

29
November 26, 2020, at 05:00 AM

Context: I have a rather large project which is a social media back end. We use MondoDB (w/ mongoose) and Express in JS. The question that I have is: Is it necessary to continue wrapping every route in try/catch blocks to ensure responses? Currently almost all (some need to return more specifc errors) of our routes look like this:

router.get('/path/to/route', async (req, res, next) => {
    try {
        // function of route
    } catch (err) {
        res.status(500).send({ status: false })
    }
}

I suspect there may be something anti-pattern about the continual use of try/catch blocks or the use of async functions for every route. My idea was to simple make a standard error handler that sends the 500 response, but then I believe that try/catch would still be necessary to use next(err)

Overall:

  • What about our code is anti-pattern?
  • Should routes use async?
  • Should try/catch blocks be continually used?
  • What is the correct pattern?

If anyone has the time to response, thank you so much.

Answer 1

You shouldn't try/catch on every route. You can use middleware to catch handle all errors and respond with the appropriate status code. A short example is:

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send({ status: false })
})

You can read more about error handling in Express here

Answer 2

I suggest creating a errorHandler.js file in your project with these contents.

class ErrorHandler extends Error {
  constructor(statusCode, message) {
    super();
    this.statusCode = statusCode;
    this.message = message;
  }
}

 const handleError = (err, res) => {
  const { statusCode, message } = err;
  res.status(statusCode).json({
    status: "error",
    statusCode,
    message
  });
};
module.exports = {
  ErrorHandler, 
  handleError
}

Then in your api.index.js you register a middleware, after importing the exported members of your errorHandler.js file, like so.

import {handleError} from errorHandler.js;
app.use((err, req, res, next) => {
  handleError(err, res);
});

then each time you want to handle a potential error, import the ErrorHandler class from the ErrorHandler.js file, and then simply use this signature

import {ErrorHandler} from errorHandler.js;
if(somethingWentAwry){
     throw new ErrorHandler(400, "something went really awry")
 }

Since the handleError function, and its use as a middle-ware in api.index.js doesn't handle next, the chain ends when you throw an error.

The solution is inspired by Chinedu Orie's post here

READ ALSO
How can i redirect user to registration page when he failed to enter correct email (ID) in AMP form?

How can i redirect user to registration page when he failed to enter correct email (ID) in AMP form?

Please kindly advise if there is walk-around to redirect to new page when amp-form validation returns error? ie

43
NodeJS : The media could not be loaded, either because the server or network failed or because the format is not supported

NodeJS : The media could not be loaded, either because the server or network failed or because the format is not supported

I have a NodeJS server and I'd like to serve a local video, but I get an error when getting the link to the html page that says: The media could not be loaded, either because the server or network failed or because the format is not supported

54
Cannot find a module after run npm install (Docker)

Cannot find a module after run npm install (Docker)

I'm trying to dockerize a node-app, but for some reason when I start the app using:

68
Trying to automate Streamloots - How to stay logged in without an authorize API?

Trying to automate Streamloots - How to stay logged in without an authorize API?

I'm trying to develop a service that listens for Twitch subscribe events (through its API) and gifts chests to the user that subscribedTwitch allows me to get an auth token for the user and get a new one everytime it expires, so that part is covered

42