In my Node.js application, I added the following code to catch every uncaught exception:
process.on('uncaughtException', function (err: Error) { try { logger.err(err); } catch (err) { } });
The problem is that Express has its own default error handler, which catches every uncaught exception. Now Express caught exceptions to Node (process.on), so my registrar did not reach. However, you can add another error handler that can catch every exception before Express:
app.use(logErrors); function logErrors (err: Error, req: Request, res: Response, next: NextFunction) { logger.err(err); next(err); }
This does not apply to all cases. Whenever I have an async function that I call with await , there is no exception, but a rejected promise is returned instead. For example:
app.get('/foo', async function (req: Request, res: Response, next: NextFunction) { await bar(); }); function bar() { throw new Exception(); }
will not reach my logErrors function because it will not throw, but will return a rejected promise.
So, to fix this, I ended my HTTP express handlers with another function:
app.get('/foo', wrap(async function (req: Request, res: Response, next: NextFunction) { await bar(); })); function wrap(func: (req: Request, res: Response, next: NextFunction) => void) { return async function (req: Request, res: Response, next: NextFunction) { try { await func(req, res, next); } catch (err) { next(err); } } }
next (err) passes the error to my handler. Now I am able to catch exceptions from my logErrors function.
I am almost ready. I still have one case where I cannot catch errors. This happens when I call the async function without the await keyword (sometimes it is useful to use the same function in two different places in the code, calling it asynchronously once and once synchronously). So this code will not catch the error:
app.get('/foo', wrap(async function (req: Request, res: Response, next: NextFunction) { bar(); }));
What happens here is that the Express HTTP handler returns the allowed promise of the wrap function. The wrapper function, in turn, does not reach the catch , so it does not call next(err) , which will reach my registrar.
bar function, in turn, returns a rejected promise, but no one expects its return value.
How can I change my code in such a way that I will not receive any raw rejection of promises? (general solution only)