问题
最近在用Node.js开发接口,使用的库主要是node+express+mysql2,在测试时出现如下错误:
Error [ERR_HTTP_HEADERS_SENT]:
Cannot set headers after they are sent to the client
# 报错的字面意思就是: 已经响应客服端请求后不能再设置headers了
也就是说同一个请求不能同时两次使用 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))
}
})
}
分析
在网上看了一下类似的问题,很多说是 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))
}
})
}
})
}
参考资料
https://blog.csdn.net/m0_46635519/article/details/123599923