Using NodeJS 10.13.0, ExpressJS 4.16.4... Got a controller handling a route that looks like this:
import { Request, Response, NextFunction } from 'express';
import braintree from 'braintree';
import config from '../../server.config';
export function index(req: Request, res: Response, next: NextFunction): void {
if(!config.braintree) throw new Error('Braintree configuration missing.');
const gateway: any = braintree.connect(config.braintree); // synchronous
return gateway.clientToken.generate({})
.then(response => res.send(response.clientToken))
.catch(next) // operational error unless config.braintree was changed
}
Reading the ExpressJS docs on error handling, I'm wondering if I'm following best practices - throwing an Error for the synchronous portion and passing the error to next() in the catch for the asynchronous portion.
Any recommendations for improvement?
Considering that promises are in use, both synchronous and asynchronous errors can be consistently handled with async
function:
export async function index(req: Request, res: Response, next: NextFunction) {
try {
if(!config.braintree)
throw new Error('Braintree configuration missing.');
const gateway: any = braintree.connect(config.braintree);
const response = await gateway.clientToken.generate({})
res.send(response.clientToken);
} catch (err) {
next(err);
}
}
Since Express doesn't support promises, async
function body should be wrapped with try..catch
. Considering that try..catch
is common for all async
middleware functions, it could be moved to a helper:
const asyncMiddleware = (middleware: RequestHandler) => async (req: Request, res: Response, next: NextFunction) => {
try {
await middleware(req, res, next);
} catch (err) {
next(err)
}
};
Which is used like:
export const index = asyncMiddleware(async (...) => {...});