无法将res.status设为404并在错误中间件中处理该状态码
解决Express异步控制器404状态码未传递到错误中间件的问题
问题原因
你的异步控制器中抛出的错误没有被Express正确捕获并传递给错误中间件。async函数中抛出的错误会以Promise Reject的形式存在,Express不会自动处理这种情况,导致错误中间件无法接收到正确的状态码;另外错误中间件中没有明确设置响应状态码,可能导致状态码被覆盖。
解决方案
1. 修正控制器代码,确保错误传递给next
将控制器中的throw new Error改为手动调用next(err),或者用try/catch包裹异步逻辑并传递错误:
方式一:直接调用next传递错误
// Controller const contact = await Contact.findById(req.params.id); if (!contact) { res.status(404); // 调用next传递错误给中间件 return next(new Error("Contact not Found")); } res.status(200).json({ message: `Got contact with id: ${req.params.id}`, contact });
方式二:使用try/catch捕获异步错误
// Controller try { const contact = await Contact.findById(req.params.id); if (!contact) { res.status(404); throw new Error("Contact not Found"); } res.status(200).json({ message: `Got contact with id: ${req.params.id}`, contact }); } catch (err) { // 将捕获的错误传递给错误中间件 next(err); }
2. 完善错误中间件,明确设置响应状态码
在错误中间件的每个case分支中,先设置响应状态码再返回JSON,确保状态码正确传递:
// Middleware Error Handler const { constants } = require("../constants"); const errorHandler = (err, req, res, next) => { const statusCode = res.statusCode ? res.statusCode : 500; console.log(statusCode); // 先设置响应状态码 res.status(statusCode); switch(statusCode) { case constants.VALIDATION_ERR: res.json({ title: "Validation Failed", message: err.message, stackTrace: err.stack, }); break; case constants.FORBIDDEN: res.json({ title: "Forbidden", message: err.message, stackTrace: err.stack, }); break; case constants.NOT_FOUND: res.json({ title: "Not Found", message: err.message, stackTrace: err.stack, }); break; case constants.UNAUTHORIZE: res.json({ title: "warning ! Unauthorized", message: err.message, stackTrace: err.stack, }); break; case constants.SERVER_ERR: res.json({ title: "Server Error", message: err.message, stackTrace: err.stack, }); break; default: console.log("no Error, Everything is Good "); res.json({ status: "ok" }); break; } } module.exports = errorHandler;
说明
- Express的错误中间件仅能处理同步代码抛出的错误,以及通过
next(err)传递的错误。对于async函数中的错误,必须手动捕获并通过next(err)传递,否则Express无法将其路由到自定义错误中间件。 - 在错误中间件中明确设置
res.status(statusCode)可以避免之前设置的状态码被覆盖,确保响应的状态码与错误类型匹配。
内容的提问来源于stack exchange,提问作者Nikhil Bolla
相关产品推荐
相关产品推荐

