为何出现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
相关产品推荐
相关产品推荐

