Express错误处理中间件未返回预期404错误,求解决方案
解决Mongoose查询无结果时错误处理中间件进入default分支的问题
问题场景
用Mongoose操作数据库,通过express-async-handler处理异步逻辑,搭配自定义errorHandler中间件捕获异常。当查询不到目标文档时,控制器里设置res.status(404)并抛出错误,但errorHandler始终走到default分支,无法返回预期的404错误响应。
控制器代码:
const asyncHandler = require('express-async-handler'); const Contact = require('../models/contactModel'); const getContact = asyncHandler(async (req, res) => { const contact = await Contact.findById(req.params.id); if (!contact) { res.status(404); throw new Error('Contact not found'); } res.status(200).json(contact); });
错误处理中间件代码:
const { constants } = require('../constants'); const errorHandler = (err, req, res, next) => { const statusCode = res.statusCode ? res.statusCode : 500; switch (statusCode) { case constants.VALIDATION_ERROR: res.json({ title: 'Validation failed', message: err.message, stackTrace: err.stack }); case constants.UNAUTHORIZED: res.json({ title: 'Unauthorized', message: err.message, stackTrace: err.stack }); case constants.FORBIDDEN: res.json({ title: 'Forbidden', message: err.message, stackTrace: err.stack }); case constants.NOT_FOUND: res.json({ title: 'Not found', message: err.message, stackTrace: err.stack }); case constants.SERVER_ERROR: res.json({ title: 'Server error', message: err.message, stackTrace: err.stack }); default: console.log('No error, all is well !'); break; } };
问题原因
- Switch Case未加break:每个case执行完后没有
break语句,代码会继续向下遍历,哪怕匹配到了constants.NOT_FOUND,最终还是会走到default分支。 - 常量值不匹配:要确认
constants文件里的NOT_FOUND数值是不是404,如果和控制器里res.status(404)设置的状态码不一致,也无法匹配对应case。
解决方案
1. 给每个Switch Case添加Break
在每个case的响应逻辑后加上break,确保匹配到对应case后终止switch执行:
const { constants } = require('../constants'); const errorHandler = (err, req, res, next) => { const statusCode = res.statusCode ? res.statusCode : 500; switch (statusCode) { case constants.VALIDATION_ERROR: res.json({ title: 'Validation failed', message: err.message, stackTrace: err.stack }); break; // 添加break case constants.UNAUTHORIZED: res.json({ title: 'Unauthorized', message: err.message, stackTrace: err.stack }); break; // 添加break case constants.FORBIDDEN: res.json({ title: 'Forbidden', message: err.message, stackTrace: err.stack }); break; // 添加break case constants.NOT_FOUND: res.json({ title: 'Not found', message: err.message, stackTrace: err.stack }); break; // 添加break case constants.SERVER_ERROR: res.json({ title: 'Server error', message: err.message, stackTrace: err.stack }); break; // 添加break default: console.log('No error, all is well !'); break; } };
2. 验证常量定义
检查constants.js文件,确保NOT_FOUND的数值为404:
// constants.js exports.constants = { VALIDATION_ERROR: 400, UNAUTHORIZED: 401, FORBIDDEN: 403, NOT_FOUND: 404, // 确认此值为404 SERVER_ERROR: 500 };
3. 可选:显式设置响应状态码
为了让前端能准确收到状态码,建议在每个case里显式设置响应的状态码(虽控制器已设置,但显式操作更稳妥):
case constants.NOT_FOUND: res.status(statusCode).json({ title: 'Not found', message: err.message, stackTrace: err.stack }); break;
验证效果
修改完成后,当查询不到文档时,控制器设置404状态码并抛错,errorHandler会正确匹配NOT_FOUND分支,返回对应错误响应,不会再进入default分支。
内容的提问来源于stack exchange,提问作者owf
相关产品推荐
相关产品推荐

