Node.js登录脚本报错:Cannot read properties of undefined (reading 'findOne')
Node.js登录页面登录报错排查与解决
问题场景
开发Node.js网页登录页面,已完成MongoDB后台配置且登录账户已存入数据库,但登录时触发如下错误:
var User = await User.findOne({ TypeError: Cannot read properties of undefined (reading 'findOne') at C:\Users\Mmart\Desktop\twitter\routes\loginRoutes.js:20:39 at Layer.handle [as handle_request] (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\layer.js:95:5) at next (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\route.js:144:13) at Route.dispatch (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\route.js:114:3) at Layer.handle [as handle_request] (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\layer.js:95:5) at C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\index.js:284:15 at Function.process_params (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\index.js:346:12) at next (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\index.js:280:10) at Function.handle (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\index.js:175:3) at router (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\router\index.js:47:12)
对应登录脚本代码:
router.post("/", async(req,res,next) => { var payload = req.body; if(req.body.logUsername && req.body.logPassword){ var User = await User.findOne({ $or: [ { username: logUsername }, { email: logUsername } ] }) .catch((error) => { console.log(error); payload.errorMessage = "something went wrong."; res.status(200).render("login", payload); }); if (user != null){ var result = bcrypt.compare(req.body.logPassword,user.Password); if(result === true){ req.session.user = user; return res.redirect("/"); } } payload.errorMessage = "login creds wrong."; return res.status(200).render("login", payload); } payload.errorMessage = "check values"; res.status(200).render("login"); })
错误原因与解决办法
1. 变量命名冲突(核心错误)
代码中用var User = await User.findOne(...),当前作用域的User变量覆盖了外部导入的Mongoose模型User。由于await是异步操作,执行到User.findOne时,当前作用域的User还未赋值,导致调用findOne时User为undefined,触发报错。
解决:
将查询结果变量名改为小写user(或其他不冲突名称):
var user = await User.findOne({ $or: [ { username: req.body.logUsername }, { email: req.body.logUsername } ] })
2. 未定义变量logUsername
代码中直接使用logUsername但未声明,该变量需从req.body中获取。
解决:
提前声明变量或直接使用req.body.logUsername:
const logUsername = req.body.logUsername; // 或直接在查询条件中写req.body.logUsername
3. bcrypt.compare是异步函数
bcrypt.compare返回Promise对象,直接用=== true判断会得到false,因为Promise不等于布尔值true。
解决:
用await等待异步结果:
var result = await bcrypt.compare(req.body.logPassword, user.password); // 注意:确保user.password与Mongoose模型中定义的密码字段大小写一致
4. 变量大小写不一致
代码中查询结果用小写user,但后续判断if (user != null)时,若前面变量名错误会导致user未定义;同时注意数据库中密码字段的大小写(比如user.Password vs user.password),必须与模型定义一致。
5. 确认模型导入
确保在loginRoutes.js顶部正确导入User模型:
const User = require('../models/User'); // 根据实际文件路径调整
修正后的完整代码示例
const bcrypt = require('bcrypt'); const User = require('../models/User'); // 确认模型路径正确 router.post("/", async(req,res,next) => { var payload = { ...req.body }; if(req.body.logUsername && req.body.logPassword){ try { const logUsername = req.body.logUsername; const user = await User.findOne({ $or: [ { username: logUsername }, { email: logUsername } ] }); if (user != null){ const result = await bcrypt.compare(req.body.logPassword, user.password); if(result){ req.session.user = user; return res.redirect("/"); } } payload.errorMessage = "登录凭据错误。"; } catch (error) { console.log(error); payload.errorMessage = "服务器出错,请稍后重试。"; } return res.status(200).render("login", payload); } payload.errorMessage = "请填写完整的用户名/邮箱和密码。"; res.status(200).render("login", payload); })
内容的提问来源于stack exchange,提问作者Mitchell
相关产品推荐
相关产品推荐

