• 基于Node.js API开发:Error [ERR_HTTP_HEADERS_SENT]


    问题

    最近在用Node.js开发接口,使用的库主要是node+express+mysql2,在测试时出现如下错误:

    Error [ERR_HTTP_HEADERS_SENT]: 
    Cannot set headers after they are sent to the client
    
    # 报错的字面意思就是: 已经响应客服端请求后不能再设置headers了
    
    • 1
    • 2
    • 3
    • 4

    也就是说同一个请求不能同时两次使用 res.send 方法。

    我的代码如下:

    // 用户注册
    exports.register = (req, res) => {
    	// 接收表单数据
    	const data = req.body
    	
    	// 数据校验
    	if (!data.username || !data.password) {
    	  return res.send(result(1, '用户名或密码不能为空!', data))
    	}
    	
    	// 重复校验
    	const select = `select * from dc_user where username=?`
    	db(select, [data.username], function (err, results) {
    	  if (err) {	// SQL异常
    	    return res.send(result(1, err.message))
    	  } else if (results.length > 0) {		// 重复
    	    return res.send(result(1, '用户名已存在!', results))
    	  }
    	  
    	})
    	
    	// 创建用户
    	const create = `insert into dc_user(username, password) values(?, ?)`
    	db(create, [data.username, data.password], function (err, results) {
    		
    		if (err) {	// SQL异常
    			return res.send(result(1, err.message))
    		} else {	// 注册成功
    			return res.send(result(0, '注册成功!', results))
    		}
    	  
    	})
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    分析

    在网上看了一下类似的问题,很多说是 res.send 使用错误,每个res.send 前都应该加上 return 我这里其实是不存在这个问题,也没有逻辑上的低级错误。
    后来看了一篇分析跟我的问题很像:也就是我这里的 db 查询是异步的,两个 db 平行执行会有两次 res.send 返回,所有才会报错。

    解决

    找到问题就很好解决了,将两次查询嵌套即可,代码如下:

    // 用户注册
    exports.register = (req, res) => {
    	// 接收表单数据
    	const data = req.body
    	
    	// 数据校验
    	if (!data.username || !data.password) {
    	  return res.send(result(1, '用户名或密码不能为空!', data))
    	}
    	
    	// 重复校验
    	const select = `select * from dc_user where username=?`
    	db(select, [data.username], function (err, results) {
    	  if (err) {	// SQL异常
    	    return res.send(result(1, err.message))
    	  } else if (results.length > 0) {		// 重复
    	    return res.send(result(1, '用户名已存在!', results))
    	  } else {
    		  // 创建用户
    		  const create = `insert into dc_user(username, password) values(?, ?)`
    		  db(create, [data.username, data.password], function (err, results) {
    		  	
    		  	if (err) {	// SQL异常
    		  		return res.send(result(1, err.message))
    		  	} else {	// 注册成功
    		  		return res.send(result(0, '注册成功!', results))
    		  	}
    		    
    		  })
    	  }
    	  
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    参考资料

    https://blog.csdn.net/m0_46635519/article/details/123599923

  • 相关阅读:
    物联网之ESP32与微信小程序实现指示灯、转向灯
    ROS——构建一个模拟的两轮ROS机器人
    【K8S系列】第十讲:Knative 简介
    bm26 bm27 1
    scanf跳过第一个输入读入第二个输入,咋做?
    iNFTnews | 谁拥有你的数据?重新构想 Web3 的数据管理
    RobotFramework入门(二)appUI自动化之app启动
    现代循环神经网络 - 序列到序列学习
    申请实用新型专利有什么优势
    springboot使用小工具:Lombok、devtools、Spring Initailizr
  • 原文地址:https://blog.csdn.net/gaoshanliushui131/article/details/126948600