Mongoose+Node.js中model.save()后Model.find()返回null问题求助
问题根源:异步操作的执行顺序坑!
嘿,这个问题我太熟了——你踩了Node.js异步编程的经典陷阱!
你的代码里,user.save()是异步I/O操作,它不会等数据写完数据库再往下执行后续代码。你把User.findById()和User.find({})直接写在了save的回调函数外面,这就导致查询操作在保存操作还没完成、数据还没真正写入数据库的时候就跑起来了,自然查不到任何东西,返回null。
修复方案1:把查询逻辑移到save的回调里
最简单的修复就是把查询代码放到save的成功回调内,这样能保证查询是在数据成功写入数据库之后执行的:
var mongoose = require("mongoose"); var User = mongoose.model("User"); module.exports.register = function(req, res) { var user = new User(); user.name = req.body.name; user.email = req.body.email; user.setPassword(req.body.password); user.save(function(err) { if (err) { // 别忘了处理保存失败的情况! console.log(err); return res.status(500).json({ error: "保存用户失败" }); } var token = user.generateJwt(); res.status(200).json({ token: token }); // 现在执行查询,数据已经在数据库里了 User.findById(user._id, function(err, particularDocument) { if (err) { console.log(err); } else { console.log(particularDocument); // 终于能拿到正确的文档了 } }); // User.find({}) 放在这里也能查到刚保存的用户 }); };
修复方案2:用async/await简化异步逻辑(更推荐)
回调嵌套多了容易形成“回调地狱”,现代Node.js更推荐用async/await处理异步操作,代码可读性更高:
var mongoose = require("mongoose"); var User = mongoose.model("User"); // 给函数加上async关键字 module.exports.register = async function(req, res) { try { var user = new User(); user.name = req.body.name; user.email = req.body.email; user.setPassword(req.body.password); // 用await等待save操作完成 await user.save(); var token = user.generateJwt(); res.status(200).json({ token: token }); // 现在查询就能拿到数据了 const particularDocument = await User.findById(user._id); console.log(particularDocument); // 同样,User.find({})也能查到刚保存的用户 const allUsers = await User.find({}); console.log(allUsers); } catch (err) { // 统一捕获所有错误 console.log(err); res.status(500).json({ error: "操作失败" }); } };
额外小提示
- 永远不要忽略异步操作的错误处理!不管是回调里的
err还是try/catch,一定要捕获并处理错误,不然出问题了很难排查。 - Mongoose的
save()方法返回Promise,你也可以用.then().catch()的链式写法,同样能避免回调嵌套。
内容的提问来源于stack exchange,提问作者Kalpesh Prithyani
相关产品推荐
相关产品推荐

