Express+Mongoose开发触发ERR_HTTP_HEADERS_SENT报错如何解决
问题根因定位
你代码里一共有3处直接触发该报错的问题,还有2处隐含逻辑错误:
1. 首页路由重复发送响应(最核心报错原因)
你首页的Post.find查询回调里连续调用了2个响应方法:
Post.find({}, function(err, foundPosts) { res.render("home", {homeStartingContent: homeStartingContent, posts: foundPosts}); // 第一次发送响应 res.redirect("/"); // 第二次发送响应,直接触发ERR_HTTP_HEADERS_SENT报错 });
res.render执行完就已经把页面响应返回给客户端了,后续再执行res.redirect等于尝试给同一个请求再发一次跳转响应,必然触发该错误。删掉其中一个即可,如果是要渲染首页就删除res.redirect("/")。
2. /posts/:postId路由模型名写错
你前面定义模型用的是Post,但该路由里查询用的是Posts(多了后缀s),会直接触发查询报错,且你没有处理错误回调,报错后Node.js还会继续尝试执行res.render,也可能触发重复响应问题。
3. 所有数据库操作回调未处理错误
你所有的Mongoose查询回调都只写了成功逻辑,没有判断err参数:
// 错误写法 post.save(function(err) { if(!err) { res.redirect("/"); } // 如果err存在,这里没有返回任何响应,后续逻辑可能继续执行导致重复响应 }); // 正确写法 post.save(function(err) { if(err) { return res.status(500).send('保存失败'); } res.redirect("/"); });
所有回调都要加错误判断,且错误分支里的响应要加return,避免后续逻辑继续执行。
额外逻辑错误(会导致页面访问异常)
- MongoDB的
_id(ObjectId类型)是大小写敏感的,你用_.lowerCase(req.params.postId)把ID转小写后会匹配不到原数据,导致查询返回空。 /posts/:postId路由查询到空值时直接渲染模板,会导致模板变量报错,建议加空值判断。
修复后的参考代码
首页路由修复
// 假设这是你的首页路由 app.get("/", function(req, res) { Post.find({}, function(err, foundPosts) { if(err) { return res.status(500).send('查询文章失败'); } res.render("home", {homeStartingContent: homeStartingContent, posts: foundPosts}); // 删掉多余的res.redirect("/") }); })
发布路由修复
app.post("/compose", function(req, res) { const post = new Post({ title: req.body.title, body: req.body.newPost, teaser: req.body.newPost.substring(0,99) + "...", }); post.save(function(err) { if(err) { return res.status(500).send('文章保存失败'); } res.redirect("/"); }); });
文章详情路由修复
app.get("/posts/:postId", function(req, res) { // 删掉_.lowerCase转换 const requested = req.params.postId; // 模型名改为Post,加错误和空值判断 Post.findOne({_id: requested}, function(err, post) { if(err) { return res.status(500).send('查询文章详情失败'); } if(!post) { return res.status(404).send('文章不存在'); } res.render("post", {post: post}); }); });
内容的提问来源于stack exchange,提问作者Sassenach6868
相关产品推荐
相关产品推荐

