如何修复Express+PostgreSQL注册接口的Cannot set headers after they are sent错误?
用户注册接口重复响应问题解决
问题原因
你这段代码的核心问题是异步操作没有按顺序等待:
postgres.query是异步执行的,用.then()的话,代码不会等这个查询完成,就直接往下跑邮箱查询、密码哈希和插入操作- 哪怕第一个用户名查询已经返回了
res.json,后面的代码还是会继续执行,导致多次尝试给客户端发响应,触发Cannot set headers after they are sent错误
解决方案
利用函数已经是async的特性,把所有异步操作改成await,确保代码按顺序执行,一旦发现用户名/邮箱存在就直接终止后续逻辑:
module.exports.register = async (req, res, next) => { try { const { username, email, password } = req.body; // 先检查用户名是否存在 const usernameCheck = await postgres.query("SELECT * FROM users WHERE username = $1", [username]); if (usernameCheck.rows.length > 0) { return res.status(409).json({ msg: "Username is already in use", status: false, }); } // 再检查邮箱是否存在 const emailCheck = await postgres.query("SELECT * FROM users WHERE email = $1", [email]); if (emailCheck.rows.length > 0) { return res.status(409).json({ msg: "Email is already in use", status: false, }); } // 哈希密码 const hashedPassword = await bcrypt.hash(password, 10); // 插入新用户 const newUser = await postgres.query( "INSERT INTO users (username, email, password) VALUES ($1,$2,$3) RETURNING *", [username, email, hashedPassword] ); return res.json({ user: newUser.rows, status: true }); } catch (err) { next(err); } };
关键修改点
- 把所有
.then()异步调用改成await,确保前一步操作完成后才执行下一步 - 检查到用户名/邮箱存在时,用
return终止函数,避免后续代码继续执行 - 把回调形式的插入操作也改成
await,统一异步代码风格,减少嵌套 - 统一用
try/catch处理所有错误,把异常传给next处理
内容的提问来源于stack exchange,提问作者jacobcurry27
相关产品推荐
相关产品推荐

