You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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变量阻止重复响应,但问题依旧,求错误原因及解决办法。


错误原因与解决办法

错误原因

核心问题是单次请求中发送了多次响应:

  1. 当数据库为空时,执行res.redirect("/")后,代码未终止,后续继续执行了res.render(),导致同一个请求被两次响应。HTTP协议规定单次请求只能有一个响应,因此触发setHeader错误(响应头已在redirect时发送,无法再次修改)。
  2. check变量无效的原因:Item.insertMany是异步操作,res.redirect会立即执行,但后续的res.render不受check变量控制,仍然会执行。

另外,/work路由中workItems未定义,是潜在的报错点。

解决办法

  1. 在重定向后终止代码执行:在res.redirect("/")后添加return,避免后续的res.render执行。
  2. 将重定向放在异步操作的回调中:确保初始数据插入完成后再重定向,避免数据未插入就跳转导致的重复插入问题。
  3. 修复/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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:35:23