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

为何出现Error [ERR_HTTP_HEADERS_SENT]错误?附Node.js相关代码

解决ERR_HTTP_HEADERS_SENT错误

问题原因

你遇到的Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client错误,根源是在已经向客户端发送响应后,又尝试修改响应头或再次发送响应。

具体来说,你的findAll方法里:

  • 不管数据库查询成功(then块)还是失败(catch块),都已经通过res.status().json()发送了完整的HTTP响应;
  • 响应发送后,你又调用了next(),这会让Express继续执行后续的中间件,这些中间件大概率会尝试操作响应对象,导致重复设置响应头,触发错误。

另外,代码同时混用async/await和.then/.catch的写法不够规范,也容易增加逻辑混乱的概率。

解决方案

方案1:移除多余的next()调用

既然findAll已经完成了响应发送的逻辑,不需要再调用next()让后续中间件处理。同时改用try/catch替代.then/.catch,让代码更简洁易读:

class Users {
  
  static async findAll(req: Request, res: Response, next: NextFunction) {
    try {
      // 解构获取查询结果
      const [rows] = await Pools.execute("SELECT * FROM users");
      res.status(200).json(rows);
    } catch (err) {
      res.status(404).json({ error: err });
      // 不需要throw err,除非你有上层错误处理逻辑需要捕获
    }
    // 删掉原来的next()调用
  }
}

方案2:交给全局错误处理中间件处理(推荐)

如果你的项目有全局错误处理中间件,可以把错误交给它统一处理,避免在每个路由里重复写响应逻辑:

首先修改findAll方法:

class Users {
  
  static async findAll(req: Request, res: Response, next: NextFunction) {
    try {
      const [rows] = await Pools.execute("SELECT * FROM users");
      res.status(200).json(rows);
    } catch (err) {
      // 把错误传递给全局错误处理中间件
      next(err);
    }
  }
}

然后在项目中添加全局错误处理中间件(要放在所有路由之后):

// 全局错误处理中间件
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  res.status(404).json({ error: err.message || '查询失败' });
});

这样所有路由的错误都会被统一处理,代码更整洁,也能避免重复发送响应的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:21:06