Express post路由挂载表单重复提交校验中间件后无限加载如何修复
问题根因
你的代码存在4个核心问题,其中第一个直接导致首次提交无限加载:
- 中间件未覆盖数据库无访客记录的场景:首次提交时
Visitor.find({})返回空数组,for循环完全不会执行,中间件既没有返回响应也没有调用next(),请求一直挂起就会出现无限加载。 - 数组遍历方式错误:用
for...in遍历数组拿到的是数组索引字符串,而非访客记录对象,后续属性判断逻辑完全失效。 - 条件判断逻辑错误:
visitor.session === visitors.session中visitors是查询返回的整个数组,不存在session属性,判断条件永远不成立;且循环内只要第一个记录不匹配就直接调用next(),跳过了后续所有记录的校验,你现在的重复拦截功能实际是误打误撞生效的,存在严重漏洞。 - 性能缺陷:全表查询所有访客记录做校验,数据量增大后接口性能会急剧下降。
修复方案
1. 重写校验中间件
直接按当前用户的sessionID查询数据库,避免全表扫描,同时覆盖所有分支的响应/next调用:
module.exports.isRevisit = async (req, res, next) => { // 直接按当前用户sessionID查询,性能更高逻辑更清晰 const existVisitor = await Visitor.findOne({ session: req.sessionID }); if (existVisitor) { // 已提交过,返回错误页 return res.render("error", { redirectedVisitor: existVisitor }); } // 未提交过,放行到后续路由逻辑 next(); };
2. 可选优化路由逻辑
补充异常捕获,避免数据库操作报错导致请求挂起:
app.post("/home", isRevisit, async (req, res, next) => { try { const date = new Date(); const today = date.getDate(); const visitor = new Visitor({ input: req.body.input, Date: today, session: req.sessionID, }); await visitor.save(); const goodVisitorsCount = await Visitor.count({ input: "good", Date: today }); const badVisitorsCount = await Visitor.count({ input: "bad", Date: today }); const allVisitorsCount = await Visitor.count({}); res.render(`GoodOrBad/${req.body.input}`, { goodVisitorsCount, badVisitorsCount, allVisitorsCount, }); } catch (err) { // 捕获异常传递给express错误处理中间件,避免请求挂起 next(err); } });
内容的提问来源于stack exchange,提问作者sultan.301
相关产品推荐
相关产品推荐

