如何等待Mongoose列表项完成推送后再执行重定向?
问题分析与解决方案
嘿,这问题我太熟了——你当前的代码犯了一个典型的异步操作顺序错误!
你看,Mongoose的findOne().exec()和report.save()都是异步操作,它们不会阻塞代码执行。你的原代码里,res.redirect()是在report.save()刚被触发(但还没完成数据库写入)的时候就执行了。这就导致用户被立刻重定向回页面,而此时数据库里的评论还没更新,所以页面显示的还是旧数据,得手动刷新才能等到数据库写完。
要解决这个问题,你需要确保重定向操作只在数据库更新完全完成之后才执行,下面给你两种常用的实现方式:
方法一:利用回调函数(传统异步写法)
把res.redirect()放到report.save()的回调函数里,这样只有当数据库成功保存新评论后,才会触发重定向:
router.post('/get/:faultId/new_comment', function(req, res, next) { var commenter = req.body.first_name + " " + req.body.last_name; var comment = req.body.new_comment_text; var datetime = Date.now(); var comment_object = commentCreate(commenter, comment, datetime); FaultReport .findOne({ '_id': req.params.faultId }) .exec(function(err, report) { if (err) { console.error(err); return next(err); // 将错误传递给Express的错误处理中间件 } if (!report) { return res.status(404).send("对应的故障报告不存在"); } report.comment.push(comment_object); // 等待save操作完成后再重定向 report.save(function(saveErr) { if (saveErr) { console.error(saveErr); return next(saveErr); } res.redirect('/api/get/' + req.params.faultId); }); }); });
这里的关键是:save()方法的回调函数会在数据库操作完成(成功或失败)时才被调用,我们把重定向逻辑放在这里,就能保证用户跳转时,新评论已经写入数据库了。
方法二:使用async/await(更简洁的现代写法)
如果你觉得嵌套回调看起来有点乱,可以用ES6的async/await语法,让异步代码看起来像同步代码一样直观:
router.post('/get/:faultId/new_comment', async function(req, res, next) { try { var commenter = req.body.first_name + " " + req.body.last_name; var comment = req.body.new_comment_text; var datetime = Date.now(); var comment_object = commentCreate(commenter, comment, datetime); // 等待查询操作完成 const report = await FaultReport.findOne({ '_id': req.params.faultId }).exec(); if (!report) { return res.status(404).send("对应的故障报告不存在"); } report.comment.push(comment_object); // 等待保存操作完成 await report.save(); // 所有异步操作完成后再重定向 res.redirect('/api/get/' + req.params.faultId); } catch (err) { console.error(err); next(err); // 统一处理所有错误 } });
这种写法用async标记路由处理函数,然后用await等待每个异步操作完成,代码逻辑顺序更清晰,错误处理也可以通过try/catch统一管理。
另外补充一点:你原来的代码没有处理错误情况(比如查询不到对应的故障报告、保存失败等),上面的两种写法都加上了错误处理,这样能避免出现静默失败的情况,让你更容易排查问题。
内容的提问来源于stack exchange,提问作者smolloy
相关产品推荐
相关产品推荐

