Vue.js+Node.js实现Todo点击更新状态存MongoDB报找不到Todo错误
问题原因排查
- 前端传递的
todo._id为undefined:前端获取的todo列表未正确返回_id字段,或存储todos数组时丢失了该字段,导致请求路径变成http://localhost:3000/todos/undefined,后端拿到无效的todoId参数 - todoId格式不符合MongoDB ObjectId规则:MongoDB的_id为24位十六进制字符串,若传递的id长度不对、包含非法字符,mongoose的findById会直接返回null,触发404错误
- 后端路由前缀配置错误:如果后端挂载todo路由的前缀和前端请求的前缀不匹配,会导致匹配到错误路由,拿到错误的todoId参数
- 数据库集合名不匹配:mongoose定义模型时
mongoose.model('Todos', todoSchema)默认会生成todos的集合名,若手动创建的集合名拼写不一致,会导致查询不到数据
解决方法
第一步:校验前端参数
在前端updateTodo方法中添加日志,确认_id正确传递:
updateTodo(todo) { // 新增id校验逻辑 console.log('待更新的todo id:', todo._id) if (!todo._id) return console.error('todo id不存在') const todoStatus = { completed: todo.completed }; axios.put(`http://localhost:3000/todos/${todo._id}`, todoStatus) .then(response => { console.log(response); }) .catch(err => { console.log(err); }) },
同时打开浏览器网络面板,确认PUT请求的URL为http://localhost:3000/todos/[24位十六进制id]格式,todoId不为undefined。
第二步:后端新增参数校验
修改后端控制器代码,先校验todoId格式合法性,避免无效查询:
const mongoose = require('mongoose') exports.updateTodo = (req, res, next) => { const todoId = req.params.todoId; // 新增ObjectId格式校验 if (!mongoose.isValidObjectId(todoId)) { const error = new Error('无效的todo id格式'); error.statusCode = 400; throw error; } const completed = req.body.completed; Todo.findById(todoId) .then(todo => { if (!todo) { const error = new Error('Could not find todo.'); error.statusCode = 404; throw error; } todo.completed = completed; return todo.save(); }) .then(result => { res.status(200).json({ message: 'Todo updated!', todo: result }); }) .catch(err => { if (!err.statusCode) { err.statusCode = 500; } next(err); }); };
第三步:确认路由和集合配置
- 检查后端路由挂载代码,确认是
app.use('/todos', todoRouter),和前端请求的前缀一致 - 打开MongoDB可视化工具,确认集合名为
todos,集合内文档的_id和前端传递的id一致
内容的提问来源于stack exchange,提问作者Šarūnas Lekstutis
相关产品推荐
相关产品推荐

