You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS+Express+EJS+MongoDB嵌套列表新增项需刷新才显示求助

嵌套列表添加项后未即时显示的问题修复

问题背景

用NodeJS、Express、EJS和MongoDB开发嵌套列表功能,一级列表创建正常,但二级列表添加新项后,必须刷新页面或再次执行添加操作(添加操作会自动刷新页面)才能看到新项。

问题分析

核心问题出在MongoDB异步操作的处理逻辑上:

  • POST路由中,foundList.save()是异步方法,但你直接在调用save后就执行res.redirect,此时数据库可能还未完成写入,导致跳转后的GET请求读取到的仍是旧数据。
  • GET路由中多余的foundList.save()完全没必要,查询到数据后直接渲染即可,额外的save操作会引发不必要的数据库交互。

修复方案

1. 正确处理POST路由的异步保存

将foundList.save()改为带回调的形式,确保数据库写入完成后再跳转:

.post(function (req, res) {
    const customListID = req.params.customListID;
    const customListName = req.params.customListName;
    const itemName = req.body.newItem;

    const item = new Item({
        name: itemName
    });

    Country.findOne({ _id: customListID }, function (err, foundList) {
        if (err) {
            console.log(err);
            return res.redirect("/BucketList/" + customListID);
        }
        foundList.items.push(item);
        // 用回调确保保存完成后再跳转
        foundList.save(function(err) {
            if (!err) {
                res.redirect("/BucketList/" + customListID);
            } else {
                console.log(err);
                res.redirect("/BucketList/" + customListID);
            }
        });
    });
})

更推荐用async/await让代码逻辑更清晰:

.post(async function (req, res) {
    try {
        const customListID = req.params.customListID;
        const itemName = req.body.newItem;

        const item = new Item({ name: itemName });
        const foundList = await Country.findOne({ _id: customListID });
        
        foundList.items.push(item);
        await foundList.save();
        
        res.redirect("/BucketList/" + customListID);
    } catch (err) {
        console.log(err);
        res.redirect("/BucketList/" + customListID);
    }
})

2. 移除GET路由中多余的save操作

GET路由仅需查询数据并渲染,不需要额外保存:

.get(function (req, res) {
    previousRoute = "/BucketList";
    if (req.isAuthenticated()) {
        loggedIn = true;
        const customListID = req.params.customListID;
        const customListName = req.params.customListName;
        Country.findOne({ _id: customListID }, function (err, foundList) {
            if (!err) {
                if (!foundList) {
                    res.redirect("/BucketList")
                } else {
                    // 移除多余的foundList.save()
                    res.render("list", { 
                        customListID: customListID, 
                        customListName: customListName, 
                        customListCode: foundList.code, 
                        newListItems: foundList.items 
                    });
                }
            } else {
                console.log(err);
                res.redirect("/BucketList");
            }
        })
    } else {
        loggedIn = false;
        res.redirect("/login");
    }
})

3. 优化视图列表结构(可选)

当前EJS循环中每个列表项都会生成独立的<ul>标签,样式上可能不符合预期,建议将<ul>移至循环外部:

<form class="d-flex justify-content-center align-items-center mb-4"
      action="/BucketList/<%=customListID%>" method="post">
    <!-- 表单内容保持不变 -->
</form>
<!-- 将ul标签移至循环外 -->
<ul class="list-group mb-0">
    <% newListItems.forEach(function(item) { %>
        <li class="list-group-item d-flex justify-content-between align-items-center border-start-0 border-top-0 border-end-0 border-bottom rounded-0 mb-2">
            <!-- li内容保持不变 -->
        </li>
    <% }) %>
</ul>

内容的提问来源于stack exchange,提问作者Guy283

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:31:06