NodeJs/Express/MongoDb PUT请求触发ERR_HTTP_HEADERS_SENT错误求助
问题根因
- 核心错误点:
findOneAndUpdate同时使用await异步语法和回调函数,导致同一条查询被Mongoose执行两次:- 第一次执行触发回调,在回调内已经调用
res.send()返回响应给客户端 - 第二次执行尝试再次返回响应,触发
Cannot set headers after they are sent to the client错误,同时抛出Query was already executed的查询重复执行异常
- 第一次执行触发回调,在回调内已经调用
- 次要问题1:
UserModel.remove是已弃用的API,会触发驱动警告,需要替换为deleteOne - 次要问题2:
userInfo接口查询出错时仅打印日志,没有返回响应,会导致客户端超时
修正方案
直接统一使用async/await语法处理所有数据库操作,移除回调函数即可:
const UserModel = require("../models/user.model"); const ObjectID = require("mongoose").Types.ObjectId; module.exports.getAllUsers = async (req, res) => { try { const users = await UserModel.find().select("-password"); res.status(200).json(users); } catch (err) { res.status(500).json({ message: err }); } }; module.exports.userInfo = async (req, res) => { if (!ObjectID.isValid(req.params.id)) return res.status(400).send("ID unknown : " + req.params.id); try { const user = await UserModel.findById(req.params.id).select("-password"); res.send(user); } catch (err) { console.log("Id unknown" + err); res.status(500).send("Id unknown" + err); } }; module.exports.updateUser = async (req, res) => { if (!ObjectID.isValid(req.params.id)) return res.status(400).send("ID unknown : " + req.params.id); try { const updatedUser = await UserModel.findOneAndUpdate( { _id: req.params.id }, { $set: { bio: req.body.bio } }, { new: true, upsert: true, setDefaultsOnInsert: true } ); res.send(updatedUser); } catch (err) { return res.status(500).json({ message: err }); } }; module.exports.deleteUser = async (req, res) => { if (!ObjectID.isValid(req.params.id)) return res.status(400).send("ID unknown : " + req.params.id); try { // 替换弃用的remove为deleteOne await UserModel.deleteOne({ _id: req.params.id }); res.status(200).json({ message: "Successfully deleted. " }); } catch (err) { return res.status(500).json({ message: err }); } };
验证
修改完成后调用PUT更新接口,数据库更新正常,不会再抛出重复查询和响应头重复设置的错误。
内容的提问来源于stack exchange,提问作者fr_aken_7
相关产品推荐
相关产品推荐

