使用POST方法向MongoDB请求时响应加载无数据的排查求助
POST请求MongoDB无响应且控制台输出“No error”问题排查
问题描述
使用POST方法向MongoDB发送请求时,响应体持续加载无数据返回,控制台打印错误处理switch语句的默认输出“No error”。
相关代码
控制器代码
const express=('express'); // 语法错误:应为require('express') const asynchandler=require('express-async-handler'); const schema=require('../models/DatabaseSchema'); const PutUser=asynchandler(async(req,res)=>{ console.log("Update a post"); }); const postUser=asynchandler(async(req,res)=>{ const {course,StudentNo}=req.body; if(!course || !StudentNo){ res.status(400); throw new Error({message:"No course info"}); // 错误:Error构造函数应传入字符串 } const userInfo=await schema.create({ course,StudentNo }); res.status(200).json(userInfo); res.end("Ending response"); // 错误:res.json已自动结束响应,重复调用会破坏响应流程 }); module.exports={postUser,getUser,PutUser,DeleteUser} // 错误:getUser、DeleteUser未定义
错误处理代码
const express=('express'); const {AUTHENTICATION_ERROR,SERVER_ERROR}=require('../constant'); // 错误:参数顺序应为(err, req, res, next),且未向客户端返回响应 const Data=(req,res,err)=>{ const responsecheck=res.statusCode?res.statusCode:500 switch(responsecheck){ case AUTHENTICATION_ERROR: ({ title:"Authentication error", message:err.message, }); break; case SERVER_ERROR: ({ title:"Server error", message:err.message }); break; default: console.log("No error"); break; } } module.exports=Data;
模型代码
const mongoose=require("mongoose"); const mongooseDatabase=mongoose.Schema({ course:{ type:String, required:true }, StudentNo:{ type:String, required:true } }); module.exports=mongoose.model("Course1",mongooseDatabase)
server.js代码
const express=require('express'); const app=express(); const dotenv=require('dotenv').config(); const errorhandle=require('./errorhandling/errorhandler'); const DatabaseConnection=require('./DatabaseConnection/DbConnection'); DatabaseConnection(); const port=process.env.PORT||5000; app.use(express.json()); app.use(errorhandle); // 错误:错误处理中间件应放在路由之后,否则无法捕获路由内错误 app.use('/user/userdetails',require("./routes/UserRoutes")); app.listen(port,()=>{ console.log('This your new port'); })
路由代码
const express=require('express'); const router=express.Router(); const{getUser,postUser,DeleteUser,PutUser}=require('../controllers/UserController'); // 注意:getUser、DeleteUser未定义 router.route('/').post(postUser).get(getUser); router.route('/:id').put(PutUser).delete(DeleteUser); module.exports=router;
注:switch语句中服务器错误(SERVER_ERROR)状态码为400,认证错误(AUTHENTICATION_ERROR)状态码为401。
问题原因分析
- 响应重复结束:控制器中
res.json(userInfo)已自动完成响应,后续调用res.end会破坏响应流程,导致前端无法正确接收结果。 - 错误中间件顺序错误:server.js中错误处理中间件放在路由之前,Express按顺序执行中间件,此时路由未执行,无法捕获路由内抛出的错误。
- 错误中间件参数错误:Express错误中间件必须遵循
(err, req, res, next)的参数顺序,现有代码顺序颠倒,无法正确捕获错误对象。 - 错误处理未返回响应:错误处理函数仅在控制台输出或定义对象,但未通过
res.json/res.send向客户端返回响应,导致前端一直等待。 - 错误抛出方式错误:
throw new Error({message:"No course info"})中,Error构造函数仅接受字符串参数,传入对象会导致错误信息异常。 - 未定义函数导出:控制器导出了未定义的
getUser和DeleteUser,导致路由引入时出现未捕获的引用错误。
解决方案
1. 修复控制器代码
const express=require('express'); // 修正语法错误 const asynchandler=require('express-async-handler'); const schema=require('../models/DatabaseSchema'); const PutUser=asynchandler(async(req,res)=>{ console.log("Update a post"); // 补充更新逻辑示例 const user = await schema.findByIdAndUpdate(req.params.id, req.body, {new: true}); if(!user){ res.status(404); throw new Error("User not found"); } res.status(200).json(user); }); const postUser=asynchandler(async(req,res)=>{ const {course,StudentNo}=req.body; if(!course || !StudentNo){ res.status(400); throw new Error("No course info"); // 修正为字符串错误信息 } const userInfo=await schema.create({ course,StudentNo }); res.status(200).json(userInfo); // 移除res.end,res.json已自动结束响应 }); // 补充getUser函数 const getUser=asynchandler(async(req,res)=>{ const users = await schema.find(); res.status(200).json(users); }); // 补充DeleteUser函数 const DeleteUser=asynchandler(async(req,res)=>{ const user = await schema.findByIdAndDelete(req.params.id); if(!user){ res.status(404); throw new Error("User not found"); } res.status(200).json({message: "User deleted successfully"}); }); module.exports={postUser,getUser,PutUser,DeleteUser}
2. 修复错误处理中间件
const {AUTHENTICATION_ERROR,SERVER_ERROR}=require('../constant'); // 修正参数顺序,并添加响应返回逻辑 const errorHandler=(err, req, res, next)=>{ const statusCode = res.statusCode ? res.statusCode : 500; let responseData; switch(statusCode){ case AUTHENTICATION_ERROR: // 401 responseData = { title:"Authentication error", message:err.message || "Authentication failed" }; break; case SERVER_ERROR: // 400 responseData = { title:"Server error", message:err.message || "Bad request" }; break; default: console.log("No error matched:", err.message); responseData = { title:"Unknown error", message:err.message || "An unexpected error occurred" }; break; } // 向客户端返回错误响应 res.status(statusCode).json(responseData); } module.exports=errorHandler;
3. 调整server.js中间件顺序
const express=require('express'); const app=express(); const dotenv=require('dotenv').config(); const errorhandle=require('./errorhandling/errorhandler'); const DatabaseConnection=require('./DatabaseConnection/DbConnection'); DatabaseConnection(); const port=process.env.PORT||5000; app.use(express.json()); // 先挂载路由,再挂载错误处理中间件 app.use('/user/userdetails',require("./routes/UserRoutes")); app.use(errorhandle); app.listen(port,()=>{ console.log(`Server running on port ${port}`); })
4. 验证数据库连接
确保DatabaseConnection.js中的数据库连接逻辑正确,能够成功连接MongoDB,避免因连接失败导致的操作异常。
内容的提问来源于stack exchange,提问作者Jaden Appiah
相关产品推荐
相关产品推荐

