Express error handling and async waiting

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)

+7
javascript promise asynchronous express
source share
3 answers

There is another process.on event in which you can configure the listener for unhandledRejection .

You can use it to handle these failures throughout the code.

NOTE Remember to complete your process after you have registered all that you need. Read more about it here .

+1
source share

I found a solution:

 app.get('/foo', async function (req: Request, res: Response, next: NextFunction) { dontAwait(() => bar()); }); async function dontAwait(func: () => void) { try { await func(); } catch (err) { logErrors(err); } } 
+1
source share

I still have one case in which I cannot catch errors.

You could, but right now you are simply not doing anything with the result. If you want your regular error handlers to start, you need to await it.

This happens when I call the async function without the await keyword

I see no good reason for this. But if you really want a fire and forget the function , you can do it. You just need to explicitly handle the errors:

 bar().catch(e => logger.err(e)); 
+1
source share

All Articles