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

MongoDB记录更新成功但控制台报ERR_HTTP_HEADERS_SENT错误求助

问题根源分析与解决方案

你遇到的ERR_HTTP_HEADERS_SENT错误本质是在同一个请求周期内多次向客户端发送HTTP响应,这是Express里非常典型的常见错误。结合你的代码和报错信息,具体问题有两处:

1. 重复发送响应

在findByIdAndUpdate的then回调里,你连续调用了res.json(updatedContact)和.send({ message: "Updated" }):

return res.json(updatedContact).send({ message: "Updated" });

res.json()方法已经完成了响应的完整发送(包括设置响应头和响应体),之后再调用res.send()会尝试再次修改响应头,这就触发了"Cannot set headers after they are sent"的报错。

2. 错误的状态码设置方式

在catch回调里,你用了res.send(402).json({ name: e.name }),这是错误的写法:

  • res.send()的参数是响应体内容,不是状态码;
  • 正确设置状态码的方式是先用res.status(状态码)指定状态,再调用响应方法。

修正后的代码

把这两处问题修复后,代码应该是这样的:

app.put("/api/persons/:id", (req, res) => {
  console.log(JSON.stringify(req.body));
  const id = req.params.id; // 无需用Object()包装,req.params.id本身就是字符串类型
  const body = req.body;
  const newPerson = {
    name: body.name,
    number: body.number,
    date: new Date(),
  };
  Contact.findByIdAndUpdate(id, newPerson, { new: true })
    .then((updatedContact) => {
      console.log("**** ", updatedContact);
      // 把响应内容合并到一个json里,只发送一次响应
      return res.json({
        contact: updatedContact,
        message: "Updated"
      });
    })
    .catch((e) => {
      console.log("error: ", e.name);
      // 正确设置状态码并发送错误响应
      res.status(402).json({ name: e.name });
    });
});

额外优化建议

  • 不需要用Object(req.params.id)包装参数,req.params.id本身就是字符串,Mongoose的findByIdAndUpdate可以直接接收;
  • 推荐用async/await语法替代Promise链式调用,代码可读性更高,错误处理也更直观:
app.put("/api/persons/:id", async (req, res) => {
  try {
    console.log(JSON.stringify(req.body));
    const id = req.params.id;
    const body = req.body;
    const newPerson = {
      name: body.name,
      number: body.number,
      date: new Date(),
    };
    const updatedContact = await Contact.findByIdAndUpdate(id, newPerson, { new: true });
    console.log("**** ", updatedContact);
    res.json({
      contact: updatedContact,
      message: "Updated"
    });
  } catch (e) {
    console.log("error: ", e.name);
    res.status(402).json({ name: e.name });
  }
});

这样修改后,既能保证数据正常更新,也不会再出现重复发送响应的错误,同时UnhandledPromiseRejectionWarning也会消失,因为所有Promise的错误都被catch块妥善处理了。

内容的提问来源于stack exchange,提问作者Ketan Ramteke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:10:28