0

I'm using express with async/await. When an async function is rejected, exception is thrown. However, the client will not get a response for his request, leaving him hanging in the air.

How should I add a global exception handler for unhandled runtime exceptions? On these cases, server should reply with "Server Error" status code 500.

  • I don't want to wrap all of my server side functions with try and catch
  • I don't want to hint the next request handler there was an error (e.g. next(err);)
  • I've read https://expressjs.com/en/guide/error-handling.html, couldn't find something as simple as I describe (have I missed something?)

This is my example express app:

const express = require('express');
const app = express();
const port = 8080;

async function validate() {
    let shouldFail = Math.random() >= 0.5;
    if (shouldFail) {
        throw new Error();
    }
}

app.get('/', async (req, res) => {
    await validate();
    res.json({"foo": "bar"});
});

app.listen(port, () => console.log(`listening on port ${port}!`));

Note - the http function will fail randomly. It's just for demo purposes.

Jossef Harush Kadouri
  • 32,361
  • 10
  • 130
  • 129
  • use https://www.npmjs.com/package/express-promise-router in this case no need to wrap the code inside try catch , it will be handled by `express-promise-router` – Joel Joseph Jan 21 '19 at 11:39
  • just install the package and include the following code `const router = require("express-promise-router")();` which will used instead of normal express router – Joel Joseph Jan 21 '19 at 11:51
  • 1
    Why don't you want to use `next`? It's the pattern recommended by the authors. – nicholaswmin Jan 21 '19 at 12:35
  • @NikKyriakides - using `next()` makes my code error-aware, I want simplicity. fire and forget, knowing that some part of the ecosystem will handle that – Jossef Harush Kadouri Jan 21 '19 at 12:40
  • It sounds like you're setting yourself up for major issues down the road. I can't elaborate in a comment why what you're trying to do sounds unwise. – nicholaswmin Jan 21 '19 at 12:42
  • @NikKyriakides - let's chat - https://chat.stackoverflow.com/rooms/187052/https-stackoverflow-com-questions-54287923 – Jossef Harush Kadouri Jan 21 '19 at 12:54
  • No, you cannot add a *global* exception handler, as it wouldn't know from which request the exception came. – Bergi Jan 21 '19 at 19:40

2 Answers2

2

This is not supported in express out of the box. However, can be achieved with a minimalistic wrapper function.

Define the following function somewhere common,

function unhandledExceptionsHandler(asyncFunction) {
    return async (req, res, next) => {
        try {
            await asyncFunction(req, res, next);
        }
        catch (e) {
            // TODO Log error internally
            res.status(500).send("Server Error");
        }
    }
}

Wrap your callback function,

app.get('/', unhandledExceptionsHandler(async (req, res) => {
    await validate();
    res.json({"foo": "bar"});
}));
Jossef Harush Kadouri
  • 32,361
  • 10
  • 130
  • 129
-2

express has built in error handling mechanism. You can configure generic error handler by adding a interceptor.

const express = require('express');
const app = express();
const port = 8080;

async function validate() {
    let shouldFail = Math.random() >= 0.5;
    if (shouldFail) {
        throw new Error();
    }
}

app.get('/', async (req, res) => {
    await validate();
    res.json({"foo": "bar"});
});

// This interceptor will be called with err object if any of the above code breaks
// This should always be a last interceptor
app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

app.listen(port, () => console.log(`listening on port ${port}!`));

You can read more about express error handling here.

Ganapati V S
  • 1,571
  • 1
  • 12
  • 23
  • 1
    This will not work if you don't catch the error and pass it to the error handling middleware with `next(err)`. – Stavros Dec 28 '19 at 17:44