Node.js+MongoDB项目页面正常但控制台报ServerResponse.setHeader错误求助
问题:Express+EJS+Mongoose待办清单项目控制台持续抛出响应错误
基于Express、EJS和Mongoose开发的待办清单项目,页面能正常显示内容,但控制台持续抛出如下错误:
at new NodeError (node:internal/errors:387:5) at ServerResponse.setHeader (node:_http_outgoing:603:11) at ServerResponse.header (D:\web development\todolist-v2-starting-files\node_modules\express\lib\response.js:767:10) at ServerResponse.send (D:\web development\todolist-v2-starting-files\node_modules\express\lib\response.js:170:12) at done (D:\web development\todolist-v2-starting-files\node_modules\express\lib\response.js:1004:10) at tryHandleCache (D:\web development\todolist-v2-starting-files\node_modules\ejs\lib\ejs.js:257:5) at View.exports.renderFile [as engine] (D:\web development\todolist-v2-starting-files\node_modules\ejs\lib\ejs.js:482:10) at View.render (D:\web development\todolist-v2-starting-files\node_modules\express\lib\view.js:135:8) at tryRender (D:\web development\todolist-v2-starting-files\node_modules\express\lib\application.js:640:10) at Function.render (D:\web development\todolist-v2-starting-files\node_modules\express\lib\application.js:592:3)
项目代码:
const express = require("express"); const bodyParser = require("body-parser"); const mongoose = require("mongoose"); const app = express(); app.set('view engine', 'ejs'); app.use(bodyParser.urlencoded({extended: true})); app.use(express.static("public")); mongoose.connect("mongodb://localhost:27017/toDoListDB",function(err){ if(err) console.log("Here is the error"); else console.log("Successfully connected to MongoDB"); }); const itemsSchema = new mongoose.Schema({ name:String }); const Item = mongoose.model("Item",itemsSchema); const item1 = new Item({ name: "Complete this course" }); const item2 = new Item({ name: "Complete RPA course" }); const item3 = new Item({ name: "Learn Programming" }); const defaultArray = [item1, item2, item3]; app.get("/", function(req, res) { let check=false; Item.find(function(err,item){ if(err) console.log("Error in finding "); else{ if(item.length==0){ Item.insertMany(defaultArray,function(err){ if(err) console.log("Error in inserting "); else console.log("Successfully saved"); }); if(check==false){ res.redirect("/"); check=true; } } res.render("list", {listTitle: "Today", newListItems: item}); } }) }); app.post("/", function(req, res){ const itemName = req.body.newItem; if(itemName!=""){ const item = new Item({ name: itemName, }); item.save(); } res.redirect("/"); }); app.get("/work", function(req,res){ res.render("list", {listTitle: "Work List", newListItems: workItems}); }); app.get("/about", function(req, res){ res.render("about"); }); app.listen(3000, function() { console.log("Server started on port 3000"); });
尝试用check变量阻止重复响应,但问题依旧,求错误原因及解决办法。
错误原因与解决办法
错误原因
核心问题是单次请求中发送了多次响应:
- 当数据库为空时,执行
res.redirect("/")后,代码未终止,后续继续执行了res.render(),导致同一个请求被两次响应。HTTP协议规定单次请求只能有一个响应,因此触发setHeader错误(响应头已在redirect时发送,无法再次修改)。 check变量无效的原因:Item.insertMany是异步操作,res.redirect会立即执行,但后续的res.render不受check变量控制,仍然会执行。
另外,/work路由中workItems未定义,是潜在的报错点。
解决办法
- 在重定向后终止代码执行:在
res.redirect("/")后添加return,避免后续的res.render执行。 - 将重定向放在异步操作的回调中:确保初始数据插入完成后再重定向,避免数据未插入就跳转导致的重复插入问题。
- 修复/work路由的未定义变量问题:要么定义
workItems,要么改为从数据库查询工作类待办项(根据项目需求)。
修改后的核心代码(app.get("/")部分)
app.get("/", function(req, res) { Item.find(function(err, items){ if(err) { console.log("Error in finding "); } else { if(items.length === 0) { // 插入完成后再重定向 Item.insertMany(defaultArray, function(err){ if(err) { console.log("Error in inserting "); } else { console.log("Successfully saved default items"); // 插入完成后重定向,避免数据未就绪 res.redirect("/"); } }); } else { // 有数据时直接渲染页面 res.render("list", {listTitle: "Today", newListItems: items}); } } }); });
修复/work路由示例(如果需要独立工作清单)
可以新增工作项的模型或使用分类字段,这里先临时定义一个空数组避免报错:
// 在顶部定义 const workItems = []; app.get("/work", function(req,res){ res.render("list", {listTitle: "Work List", newListItems: workItems}); });
内容的提问来源于stack exchange,提问作者Teja Sruthi Varanasi
相关产品推荐
相关产品推荐

