Omar Murcia
Omar Murcia

Reputation: 567

How to return a JSON response in errorHandler Middleware in NodeJS using Express?

How to return a JSON response from errorHandler Middleware in NodeJS using Express. My code is:

UserController.js

const UserService = require("../services/UserService");

exports.createUser = async (req, res) => {
    try {
        throw new Error("Error from UserController");
    } catch (error) {
        throw error;
    }
};

index.js

const express = require("express");
const conectarDB = require("./config/DBConfig");
const cors = require("cors");

//Crear el servidor
const app = express();

//Conectar a la BD
conectarDB();

//Habilitar cors
app.use(cors());

//Habilitar express.json
app.use(express.json({ extended: true }));

//Puerto de la app
const PORT = process.env.PORT || 4000;

//Rutas
app.use("/api/user", require("./routes/UserRoute"));

//ErrorHandler middleware 
app.use(function (err, req, res, next) {
    res.status(500).json({ error: err.message });
});

//Arrancar el app
app.listen(PORT, () => {
    console.log(`El servidor está funcionando en el puerto ${PORT}`);
});

UserRoute.js

const express = require("express");
const router = express.Router();
const UserController = require("../controllers/UserController");

router.post("/", UserController.createUser);

module.exports = router;

I would like to get a JSON response from my errorHandler middleware, like that:

{
  error: "Error from UserController"
}

My current code doesn't work. it doesn't return any JSON response.

Thanks in advance.

Upvotes: 0

Views: 177

Answers (2)

Bergur
Bergur

Reputation: 4057

As @Won Gyo Seo mentions you need to use next to call the next middlewere in the stack, if you don't you'll never reach your error handler. That means putting catch and next on every route. I understand if you don't want to do that.

One way would be to make a helper function

bindAndCatch (fn) {
  return function(req, res, next) {
    fn(req, res, next)
      .then(res.json.bind(res))
      .catch(next)
  }

You can now do

router.get('/user', bindAndCatch((req) => {
  return createUser(req.id)
}))

It will return the promise and catch the error, call the next middlewere and pass the error to it.

Upvotes: 2

Won Gyo Seo
Won Gyo Seo

Reputation: 442

Did you handle the error properly in the router earlier?

For example, as below.

router.get('/user', async (req, res, next) => {
  try {
    
    .... // some logics...

  } catch (err) {
    // you should call 'next' for throwing error to your error handler.
    next(err);
  }
});

Upvotes: 2

Related Questions