ChikChak
ChikChak

Reputation: 1034

Express error middleware without `next()`?

I'm using Express and I want to use the build-in middlewares to handle errors.

I'm using it this way -

app.use((err,req,res,next)=> {
    console.log('error');
)};

Now this middleware is reached only if I'm using next(error) (where error is object of type Error) in my router. On the other hand, if I simply throw new Error() in my router, the middleware is not called.

Is there any way to omit the next()? So that if any error is thrown in my router, it will be handled by the middleware?

Upvotes: 0

Views: 1960

Answers (2)

Victor Parmar
Victor Parmar

Reputation: 5789

If you can use Node.js >= 8 that comes with async/await then you can use the following wrapper function over your routes:

const wrap = fn => {
  return async function(req, res, next) {
    let e = null;
    try {
      await fn(req, res, next);
    } catch (err) {
      e = err;
      next(err);
    }

    if (!e) {
      next();
    }
  };
};

    app.get(
      "/path",
      wrap(async (req, res) => {
        // use sync style code here which can throw
      })
    );

Upvotes: 4

jfriend00
jfriend00

Reputation: 707326

If the throw is synchronous, you could invent your own request handler wrapper that would catch any exceptions and turn them into a call to next():

app.get2 = function(path, fn) {
    app.get(path, function(req, res, next) {
        try {
            fn(req, res, next);
        } catch(err) {
            next(err);
        }
    });
};

And, sample usage:

app.get2("/test", function(req, res, next) {
    throw new Error("testing...");    // will end up in next()
});

Then, if your fn function throws synchronously, then it will be caught by your get2() wrapper and will automatically call next(err) for you.

If you're throwing asynchronously, this won't work. There is no generic wrapper for asynchronous throws because throws into an asynchronous callback don't throw to your code - they throw back into the asynchronous infrastructure for whatever async operation you were using and only they can catch it. If you use promises exclusively for your asynchronous operations, then the promise infrastructure will automatically catch your throws and turn them into rejected promises and you could do something similar to above for a returned and rejected promise. The Koa framework (a derivative of Express) does something similar already and I think Express 5 will have some features like that to.

Upvotes: 0

Related Questions