删除任意Route条目时持续触发TypeError: Cannot read properties of null (reading 'items')
问题:删除待办条目时出现
TypeError: Cannot read properties of null (reading 'items') 在基于Express、Mongoose开发的待办清单应用中,删除任意路由下的条目时,反复触发错误:TypeError: Cannot read properties of null (reading 'items')。
错误原因
- EJS模板输入值未加引号:模板中
listName隐藏输入框的value属性未用引号包裹,当列表名称包含空格或特殊字符时,后端接收到的listName值会被截断或解析错误,导致List.findOne无法找到对应文档,返回null,后续访问foundList.items自然报错。 - 异步代码风格混乱:删除路由混合使用回调和Promise,未妥善处理异步操作的完成时机,增加了空值出现的概率。
- 废弃API使用:Mongoose的
findByIdAndRemove已被废弃,存在潜在兼容性问题。
修复方案
1. 修复EJS模板的隐藏输入框
给listName的value属性添加引号,确保值被正确传递:
<input type="hidden" name="listName" value="<%= listTitle %>">
2. 统一使用async/await重构删除路由
彻底替换回调,用async/await处理异步操作,明确空值判断逻辑:
app.post("/delete", async function(req, res) { const checkedItemId = req.body.checkbox; const listName = req.body.listName; console.log("checkboxID: " + checkedItemId); if (listName === "Today") { try { // 使用废弃API的替代方法findByIdAndDelete await Item.findByIdAndDelete(checkedItemId); console.log("Successfully deleted item."); res.redirect("/"); } catch (err) { console.log(err); res.redirect("/"); } } else { try { const foundList = await List.findOne({ name: listName }); if (foundList && foundList.items) { foundList.items.pull({ _id: checkedItemId }); await foundList.save(); res.redirect("/" + listName); } else { console.log("List or items not found."); res.redirect("/" + listName); } } catch (err) { console.log(err); res.redirect("/" + listName); } } });
3. 优化自定义列表相关的异步逻辑
自定义列表创建时等待保存完成
将app.get("/:customListName")改为async函数,等待列表保存后再重定向:
app.get("/:customListName", async function(req, res) { const customListName = req.params.customListName; const requestedUrl = req.originalUrl; if (requestedUrl === "/favicon.ico") { res.status(204).end(); return; } const foundList = await List.findOne({name: customListName}); if(!foundList){ const list = new List({ name: customListName, items: [] }); await list.save(); res.redirect("/" + customListName); } else { res.render("list", { listTitle: foundList.name, newListItems: foundList.items, }); } });
自定义列表添加条目时等待保存完成
重构app.post("/:customListName?"),确保条目保存后再重定向:
app.post("/:customListName?", async function(req, res) { const customListName = req.params.customListName; const newItem = req.body.newItem; const item = new Item({ name: newItem }); if (customListName) { try { const foundList = await List.findOne({ name: customListName }); foundList.items.push(item); await foundList.save(); res.redirect("/" + customListName); } catch (error) { console.log(error); res.redirect("/" + customListName); } } else { await item.save(); res.redirect("/"); } });
内容的提问来源于stack exchange,提问作者Mohit
相关产品推荐
相关产品推荐

