Node.js Express子路由用中间件报错:Route.post()获undefined回调
问题场景
为避免server.js主文件臃肿,拆分出包含登录、注册、邮箱验证、密码重置的auth子路由。同时编写了checkAuthenticated(验证已登录)和checkNotAuthenticated(验证未登录)两个中间件,由于不同接口需要不同身份校验逻辑,无法通过app.use()全局挂载。但在auth路由文件中导入这两个中间件并为login接口添加checkNotAuthenticated时,出现报错:Error: Route.post() requires a callback function but got a [object Undefined],移除该中间件后则正常运行。
错误原因
你在server.js中定义的checkAuthenticated、checkNotAuthenticated是普通函数,未通过module.exports导出;同时server.js先引入了authRoute,此时中间件函数还未定义,导致auth路由文件中require('../server')无法获取到这两个函数,最终checkNotAuthenticated为undefined,触发路由回调必须是函数的错误。
解决方法
最合理的方案是将身份校验相关中间件单独抽离为独立文件,既解决导出问题,也让代码结构更清晰:
步骤1:新建中间件文件
创建middleware/auth.js,把所有校验相关函数移到这里并导出:
async function checkJWT(token) { try { // 原有的JWT校验逻辑 return user; } catch (err) { console.log(err); return 500; } } async function checkAuthenticated(req, res, next) { const auth = await checkJWT(req.cookies.token); if (auth === 500) return res.status(500).send(); if (!auth) return res.status(401).send(); req.user = auth; return next(); } async function checkNotAuthenticated(req, res, next) { const auth = await checkJWT(req.cookies.token); if (auth === 500) return res.status(500).send(); if (auth) return res.status(401).send(); return next(); } module.exports = { checkAuthenticated, checkNotAuthenticated, checkJWT };
步骤2:修改server.js导入路径
从新的中间件文件导入需要的函数:
const userRoute = require("./routes/user"); const authRoute = require("./routes/auth"); const { checkAuthenticated } = require("./middleware/auth"); const app = express(); (async () => await connection())(); app.use("/auth", authRoute); app.use("/user", checkAuthenticated, userRoute); app.listen(3001, () => { console.log("backend running on Port: 3001"); });
步骤3:修改auth路由文件导入路径
同样从中间件文件导入checkNotAuthenticated:
const express = require("express"); const { checkNotAuthenticated } = require("../middleware/auth"); const router = express.Router(); router.post("/login", checkNotAuthenticated, async (req, res) => { // 原有的登录逻辑 return res.status(401).send(); }); module.exports = router;
额外说明
这种模块化拆分方式不仅解决了当前导出问题,还避免了潜在的循环依赖风险,同时让代码职责更清晰,后续维护和扩展也更方便。
内容的提问来源于stack exchange,提问作者Kes

