Express.js路由异常:文档创建成功但catch块仍执行
排查Express.js + Mongoose创建Category接口的404异常问题
问题现象
调用创建Category的接口后出现矛盾现象:
- MongoDB Compass显示文档已成功写入数据库
- 接口返回catch块的404错误响应
- 控制台打印日志:
POST /api/categories/ 404 56.973 ms - 99 - 请求体参数正常传递(控制台已输出
req.body = { name: 'Suleyman Sah Furnitures' })
相关代码
server.js
const mongoose = require("mongoose"); const dotenv = require("dotenv"); dotenv.config({ path: "./config.env" }); const app = require("./app"); mongoose .connect(process.env.LOCAL_CONN_STRING, { useNewUrlParser: true, useUnifiedTopology: true, }) .then((conn) => { console.log(`Connection successfull with : ${conn}`); }) .catch((err) => { console.log("error is: ", err); }); // 启动服务 app.listen(5000, () => { console.log("server has started"); });
app.js
// 导入模块 const express = require("express"); const morgan = require("morgan"); const app = express(); const productsRouter = require("./routes/productsRouter"); const customersRouter = require("./routes/customersRouter"); const employiesRouter = require("./routes/employiesRouter"); const addressesRouter = require("./routes/addressesRouter"); const contactsRouter = require("./routes/contactsRouter"); const categoriesRouter = require("./routes/categoriesRouter"); const subCategoriesRouter = require("./routes/subCategoriesRouter"); const ordersRouter = require("./routes/ordersRouter"); const orderProductsRouter = require("./routes/orderProductsRouter"); const paymentsRouter = require("./routes/paymentsRouter"); const pricesRouter = require("./routes/pricesRouter"); const stocksRouter = require("./routes/stocksRouter"); // 中间件配置 app.use(express.json()); if (process.env.NODE_ENV === "development") { app.use(morgan("dev")); } app.use(express.static("./public")); app.use((req, res, next) => { req.requestAt = new Date().toISOString(); next(); }); // 挂载路由 app.use("/api/products", productsRouter); app.use("/api/customers", customersRouter); app.use("/api/employies", employiesRouter); app.use("/api/addresses", addressesRouter); app.use("/api/contacts", contactsRouter); app.use("/api/categories", categoriesRouter); app.use("/api/subcategories", subCategoriesRouter); app.use("/api/orders", ordersRouter); app.use("/api/orderproducts", orderProductsRouter); app.use("/api/payments", paymentsRouter); app.use("/api/prices", pricesRouter); app.use("/api/stocks", stocksRouter); // 全局404处理 app.all("*", (req, res) => { res.status(404).json({ status: "fail", data: { message: `The requested route (${req.originalUrl}), Not found on the server!`, }, }); }); module.exports = app;
Category控制器
exports.createCategory = async (req, res) => { try { const { name } = req.body; console.log("req.body = ", req.body, "name passsed = ", name); const category = await Category.create( { name }, { new: true, runValidators: true, } ); console.log("pass validation", category); res.status(200).json({ status: "success", data: { category, }, }); } catch (err) { res.status(404).json({ status: "fail", data: { error: err.message, }, }); } };
Category Schema
const categorySchema = new mongoose.Schema({ name: { type: String, required: [true, "category must be specified"], minlength: 10, maxlength: 100, unique: [true, "Category name must be unique"], }, });
控制台日志
[nodemon] starting `node server.js` server has started Connection successfull with : [object Object] req.body = { name: 'Suleyman Sah Furnitures' } name passsed = Suleyman Sah Furnitures POST /api/categories/ 404 56.973 ms - 99
排查步骤
核对路由定义与请求路径
- 确认
categoriesRouter内是否正确定义了POST /路由(因为app.js中挂载的是/api/categories,所以路由器内应为router.post('/', createCategory)),如果路由路径不匹配,会直接落入全局404处理。 - 检查
categoriesRouter是否正确导出并挂载,确保没有拼写错误。
- 确认
分析控制器异常触发逻辑
- 控制台未打印
pass validation日志,说明Category.create()执行后直接进入catch块,尽管MongoDB已写入文档。这种情况大概率是Mongoose在写入后触发了后续异常:- 检查Category模型是否存在
post钩子(如post('save')),若钩子函数抛出异常,会导致create()的Promise拒绝。 - 验证
unique约束:MongoDB的唯一索引是否已正确创建?若索引创建延迟,可能出现写入成功后Mongoose检测到重复的情况(首次创建时概率较低)。
- 检查Category模型是否存在
- 控制台未打印
检查响应是否被中断或覆盖
- 测试将控制器内的成功响应改为简单的
res.send('test'),排除JSON序列化失败(如category对象存在循环引用)导致的异常。 - 确认控制器内没有遗漏的
next()调用,避免请求流转到全局404路由。
- 测试将控制器内的成功响应改为简单的
处理路径末尾斜杠问题
- 确认请求路径是
/api/categories还是/api/categories/,Express默认会自动兼容,但可在categoriesRouter中显式处理两种路径,或启用app.use(express.urlencoded({ extended: true }))优化路径匹配。
- 确认请求路径是
打印完整错误信息
- 修改catch块,打印完整错误对象而非仅
err.message,定位异常根源:catch (err) { console.error("Full error details:", err); res.status(400).json({ status: "fail", data: { error: err.message, stack: err.stack }, }); }
- 修改catch块,打印完整错误对象而非仅
内容的提问来源于stack exchange,提问作者Saadullah khan
相关产品推荐
相关产品推荐

