我注意到我的Express应用程序中有一个重复出现的模式,我认为可以对其进行优化。基本上,我有一条路由调用带有一些异步函数的方法。
index.js
const controller = require('./controller.js');
const router = new Router();
router.post('/user', controller.createUser);
module.exports = router;
controller.js
exports.createUser = async (req, res, next) => {
try {
// asynchronous calls, etc.
} catch (e) {
// pass error to middleware
next(e);
}
}
我的每个控制器方法中都重复出现try/catch
块。我希望将捕获的错误传递给我的错误处理中间件。因此,在我的每个控制器功能中传递错误似乎不现实且重复。我可以重构吗?
如果将控制器方法包装在这样的函数中怎么办?
index.js
const controller = require('./controller.js');
const router = new Router();
const handleErrors = (func) => async (req, res, next) => {
try { await func(req, res, next) }
catch (e) { return next(e) }
};
router.post('/user', handleErrors(controller.createUser));
module.exports = router;
controller.js
exports.createUser = async (req, res, next) => {
// asynchronous calls, etc.
if (a !== b) {
// errors can be passed to middleware as such
throw new CustomError(400, 'a is not equal to b');
}
}
这是一个合适的解决方案吗? Express是否具有完成同一件事的内置方法?我应该对以这种方式重构整个应用程序保持谨慎吗?
答案 0 :(得分:2)
这是一个合适的解决方案吗?
是的,看起来不错。
Express是否具有完成同一件事的内置方法?
不,Express是在引入async
/ await
之前编写的。
我应该以这种方式重构整个应用程序吗?
我不这么认为。我怎么写:
const handleErrors = (func) => (req, res, next) => func(req, res).then(() => next(), next);
答案 1 :(得分:1)
我建议您这篇文章:https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016
如本文所述,这应该是中间件:
const asyncMiddleware = fn =>
(req, res, next) => {
Promise.resolve(fn(req, res, next))
.catch(next);
};
这是控制器的外观:
router.get('/users/:id', asyncMiddleware(async (req, res, next) => {
/*
if there is an error thrown in getUserFromDb, asyncMiddleware
will pass it to next() and express will handle the error;
*/
const user = await getUserFromDb({ id: req.params.id })
res.json(user);
}));
router.post('/users', asyncMiddleware(async (req, res, next) => {
const user = await makeNewUser(req.body);
res.json(user)
}))