Node.js中mongoose的findOneAndUpdate执行成功却返回错误该如何解决
问题根因
你遇到的报错核心是同时混用了await异步语法和回调函数两种处理findOneAndUpdate结果的方式,导致Mongoose执行逻辑冲突,同时可能触发重复响应的报错:
- 当给
findOneAndUpdate传入回调参数时,方法不会返回Promise对象,此时外层的await不会生效,同时回调函数和外层的catch块都可能尝试给前端返回响应,同一请求两次调用res.send/res.json就会抛出服务端错误。 - 数据库可以正常更新是因为Mongoose的查询逻辑本身执行完成了,错误出现在结果返回的节点,属于异步处理逻辑冲突导致的响应异常。
修复方案
方案1:保留await,去掉回调函数(推荐,符合现代异步代码写法)
try { const docs = await userModel.findOneAndUpdate( { _id: req.params.id }, { $set: { nickName: req.body.nickName, }, }, { upsert: true, new: true, setDefaultsOnInsert: true } ); return res.send(docs); } catch (err) { return res.status(500).json({ message: err }); }
方案2:保留回调,去掉await
// 去掉await关键字,完全用回调处理结果 userModel.findOneAndUpdate( { _id: req.params.id }, { $set: { nickName: req.body.nickName, }, }, { upsert: true, new: true, setDefaultsOnInsert: true }, (err, docs) => { if (!err) return res.send(docs); else return res.status(500).send({ message: err }); } );
额外校验点
如果修改后还是报错,可以额外检查两个常见问题:
- 确认
req.params.id是合法的MongoDB ObjectId格式,或者你在userModel的_id字段定义为非ObjectId类型(比如自定义字符串) - 确认接口路由的请求方法、参数传递符合预期,
req.body.nickName没有触发schema字段校验规则报错
内容的提问来源于stack exchange,提问作者Kenyuki
相关产品推荐
相关产品推荐

