Node.js中Mongoose查询事件顺序异常问题求助
问题描述
我通过Mongoose将Node.js应用连接至MongoDB,需要检查数据库中是否存在标题为指定topic的数据。我使用find()方法遍历数据逐一与topic比对,若未找到则返回特定标识,但实际先触发了“未找到”的代码。通过console.log发现日志先输出default,再输出checking in posts,而非预期顺序。
代码片段
app.get("/posts/:topic", (req, res) => { const topic = _.lowerCase(req.params.topic); var found = false; posts.find().then((result)=>{ result.forEach((element)=>{ if(_.lowerCase(element.postTitle) === topic){ found = true; console.log("checking in posts.."); res.render("post", {postTitle: element.postTitle, postContent: element.postContent}); } }) }).catch((err)=>console.log(err)); if(found == false){ console.log("default"); // res.render("post", {postTitle: "Oops!...", postContent: "The post you are searching, does not exists.....try again."}); } });
日志输出
default checking in posts
求助如何修正事件执行顺序,让查询逻辑先执行再判断是否返回未找到标识。
解决方案
问题根源是Mongoose的find()是异步操作,它不会阻塞后续代码执行。你的if(found == false)代码会在数据库查询完成前就执行,所以此时found还是初始的false,先输出了default,之后数据库查询完成才进入then回调输出checking in posts。
可以通过以下方式修复:
方式一:将判断逻辑移至then回调内部
把未找到的处理逻辑放到find()的then回调里,确保在数据库查询完成后再执行判断:
app.get("/posts/:topic", (req, res) => { const topic = _.lowerCase(req.params.topic); posts.find().then((result)=>{ let found = false; result.forEach((element)=>{ if(_.lowerCase(element.postTitle) === topic){ found = true; console.log("checking in posts.."); res.render("post", {postTitle: element.postTitle, postContent: element.postContent}); } }); // 遍历完结果后再判断是否未找到 if(!found){ console.log("default"); res.render("post", {postTitle: "Oops!...", postContent: "The post you are searching, does not exists.....try again."}); } }).catch((err)=>{ console.log(err); // 异常情况下返回错误页面 res.render("post", {postTitle: "Error", postContent: "Something went wrong."}); }); });
方式二:使用async/await简化异步逻辑
用async/await让异步代码看起来像同步代码,更易读:
app.get("/posts/:topic", async (req, res) => { const topic = _.lowerCase(req.params.topic); try { const result = await posts.find(); let found = false; result.forEach((element)=>{ if(_.lowerCase(element.postTitle) === topic){ found = true; console.log("checking in posts.."); res.render("post", {postTitle: element.postTitle, postContent: element.postContent}); } }); if(!found){ console.log("default"); res.render("post", {postTitle: "Oops!...", postContent: "The post you are searching, does not exists.....try again."}); } } catch (err) { console.log(err); res.render("post", {postTitle: "Error", postContent: "Something went wrong."}); } });
额外优化建议
不需要用find()查询所有数据再遍历比对,直接在数据库层面过滤效率更高:
app.get("/posts/:topic", async (req, res) => { const topic = _.lowerCase(req.params.topic); try { // 直接查询匹配标题的文档,用正则实现不区分大小写匹配 const post = await posts.findOne({ postTitle: { $regex: new RegExp(`^${topic}$`, "i") } }); if(post){ console.log("checking in posts.."); res.render("post", {postTitle: post.postTitle, postContent: post.postContent}); } else { console.log("default"); res.render("post", {postTitle: "Oops!...", postContent: "The post you are searching, does not exists.....try again."}); } } catch (err) { console.log(err); res.render("post", {postTitle: "Error", postContent: "Something went wrong."}); } });
这样避免了把所有数据拉到服务器再遍历,提升了性能,尤其是数据量大的时候。
内容的提问来源于stack exchange,提问作者navneet sharma
相关产品推荐
相关产品推荐

