Express/Mongoose/MongoDB项目按指定要求配置错误处理相关问题咨询
问题1:示例代码放置位置
你可以按功能拆分存放,不需要把代码塞到现有控制器里:
- 自定义错误类建议单独创建
errors目录存放,每个错误类单独一个文件,方便后续复用和维护 - 全局错误处理中间件可以单独创建
middlewares/errorHandler.js文件导出,也可以直接写在app.js中所有路由注册代码的后面、app.listen代码的前面。更推荐抽成单独中间件文件,保持app.js的整洁。
问题2:是否需要创建自定义错误类
需要,这是目前Express项目错误处理的主流规范实现。你可以创建继承自原生Error的自定义错误类,每个类自带对应的错误状态码属性,比如:
// errors/NotFoundError.js class NotFoundError extends Error { constructor(message) { super(message); this.statusCode = 404; } } module.exports = NotFoundError;
后续你在控制器中抛出错误时,直接抛出对应错误类的实例即可,不需要每次都手动判断状态码,也避免硬编码状态码的冗余问题。
问题3:现有catch分支不符合要求的原因
你现在的写法有两个核心问题:
- 错误类型判断缺失:比如
getUser接口的catch里不管什么错误都直接返回404,但实际findById抛出的错误可能有多种:如果传入的id不符合MongoDB的id格式会抛出CastError(属于400错误),如果是数据库连接异常会抛出系统错误(属于500错误),直接统一返回404完全不符合错误响应的规范。 - 逻辑冗余:你在每个控制器的catch里都单独写响应逻辑,重复代码多,后续如果要统一调整错误返回的格式,需要逐个修改所有控制器,维护成本很高,不符合Express集中式错误处理的设计逻辑。
代码修改参考
你可以按下面的逻辑调整现有代码:
- 先在控制器中把错误都传递给全局中间件:
// 调整后的getUser逻辑 const NotFoundError = require('../errors/NotFoundError'); const BadRequestError = require('../errors/BadRequestError'); module.exports.getUser = (req, res, next) => { User.findById(req.params.id) .then((user) => { if (!user) { throw new NotFoundError('用户不存在'); } res.send({ data: user }); }) .catch((err) => { if (err.name === 'CastError') { next(new BadRequestError('传入的用户ID格式错误')); return; } next(err); }); };
- 编写全局错误处理中间件:
// middlewares/errorHandler.js module.exports = (err, req, res, next) => { const { statusCode = 500, message } = err; res .status(statusCode) .send({ message: statusCode === 500 ? '服务器内部错误' : message }); };
- 在app.js中挂载中间件:
// app.js 中路由注册后加这行 const errorHandler = require('./middlewares/errorHandler'); // ...其他代码 app.use('/cards', cardRouter); app.use(errorHandler); // 全局错误处理放在所有路由之后 app.listen(PORT, () => console.log(`listening on port ${PORT} . . .`));
内容的提问来源于stack exchange,提问作者Eddie Melendez
相关产品推荐
相关产品推荐

