如何在express的控制器中实现DRY?我发现我重复了捕获函数的代码。
exports.getUsers = (req, res) => {
Ad.find({})
.then(data=>{
res.json({status:1, data})
})
.catch(err => {
res.status(400).send({
msg: err
})
})
}
exports.getUser = (req, res) => {
User.findOneById({id: res.body.id})
.then(data=>{
res.json({status:1, data})
})
.catch(err => {
res.status(400).send({
msg: err
})
})
}
大多数时候我们只想返回相同的错误对象,但是在一个控制器文件中,我们有很多这样的
.catch(err => {
res.status(400).send({
msg: err
})
})
我们可以在任何地方实现一次作为中间件吗?
答案 0 :(得分:1)
您可以使用捕获错误的中间件来包装每条路线。
const errorHandler = fn => (req, res, next) => {
Promise.resolve(fn(req, res, next))
.catch(err => {
res.status(400).send({ msg: err.message });
});
};
app.post('/users', errorHandler(getUsers));
但是使用这种方法,每个错误都将以状态400发送,您也可能会暴露关键信息。我建议使用自定义错误将Error子类化,例如BadRequestError并在控制器中抛出此错误并更改中间件,如下所示:
const errorHandler = fn => (req, res, next) => {
Promise.resolve(fn(req, res, next))
.catch(err => {
if (err.name === 'BadRequestError') {
res.status(400).send({ msg: err.message });
} else {
// log the error
res.status(500).send({ msg: 'Internal Server Error' })
}
});
};
一个很好的副作用:通过使用errorHandler
包装每个端点,您的应用程序变得非常健壮,因为如果您的代码失败,您将始终发送响应并且永远不会在客户端获得超时。
答案 1 :(得分:0)
不是中间件,但您可以创建一个以sendErrorResponse
和res
为参数的函数err
,例如:
function sendErrorResponse(res, err) {
return res.status(400).send({
msg: err
})
}
然后将其用作:
User.findOneById({id: res.body.id}).then(data=>{
res.json({status:1, data})
})
.catch(err => sendErrorResponse(res, err))
如果需要,可以将sendErrorResponse
移到单独的文件中,并在多个控制器中使用它。