Node.js+Express+Mongoose出现ERR_HTTP_HEADERS_SENT错误如何解决
解决方案
这个错误本质是服务端已经向客户端发送过响应头之后,再次尝试修改响应头或发送新的响应内容导致的,结合你提供的代码,可以按以下步骤排查修复:
1 修正数据存在性判断逻辑
Mongoose 中Model.find()无论是否匹配到数据,都会返回数组类型:匹配到数据返回对应文档数组,无匹配时返回空数组[],而![]的布尔值为false,你当前的if(!docs)判断永远不会触发。如果需要判断无数据的场景,将判断条件修改为docs.length === 0。
2 为Controller的Promise链式调用添加return
你当前的代码没有返回Promise实例,极端场景下如果Controller内还有Promise之外的后续代码执行,可能会触发重复返回响应的问题,在promise前添加return终止后续代码执行。
3 响应前先判断是否已发送过响应头
可以在catch返回响应前增加res.headersSent判断,避免已经发送过响应的场景下重复发送。
4 排查路由重复定义
检查所有路由文件,确认是否存在多处定义GET /api/v1/database路由的情况,如果同一个路由绑定了多个处理函数,且多个函数都执行了返回响应的操作,就会触发该报错。
5 排查全局中间件冲突
- 如果你同时使用了
cors第三方包和自定义的CORS中间件,建议统一使用其中一种CORS配置,避免重复设置响应头 - 检查是否存在全局错误处理中间件,在catch已经返回响应之后,错误中间件又再次执行返回响应的操作
修改后的Controller示例代码
exports.databaseController = (req, res) => { const promise = Database.find({}).exec() // 添加return终止Controller后续逻辑执行 return promise .then(docs => { // 修改空数据判断逻辑 if (docs.length === 0) { throw new Error('docs not found') } console.log(docs) return res.status(200).json(docs) }) .catch(err => { console.log(err) // 先判断是否已经发送过响应头,避免重复发送 if (!res.headersSent) { return res.status(404).json({ err: err.message }) } }) }
如果修改后仍然报错,可以在res.status(200)和res.status(404)前分别添加日志,确认是否同一个请求触发了两次响应返回逻辑。
内容的提问来源于stack exchange,提问作者davijose40
相关产品推荐
相关产品推荐

