Node.js异步触发ERR_HTTP_HEADERS_SENT报错该如何修复?
报错根因分析
这个Error [ERR_HTTP_HEADERS_SENT]报错的本质是同一个HTTP请求内多次调用了res.redirect()/res.render()等发送响应的方法:Node.js在第一次调用响应方法后就会把响应头发送给客户端,后续再尝试修改响应头、发送新响应就会抛出该错误。
你当前代码的核心问题是所有逻辑没有做异步流程控制和终止判断:
- 密码校验触发
res.redirect('/signup')后没有终止代码执行,后续的邮箱校验、用户名校验、插入用户逻辑会继续运行,这些逻辑里的其他res操作就会触发重复响应报错 - 数据库查询用的是回调式异步写法,多个查询是并行执行的,很容易出现邮箱校验已经触发重定向,用户名校验、插入逻辑还在异步运行的情况,所以才会出现重定向后仍然执行数据库插入的问题
- 额外问题:你当前的SQL是字符串拼接写法,存在SQL注入高危风险,必须修改为参数化查询
修复方案
推荐将回调式异步逻辑改为async/await写法,既方便做流程控制,可读性也更高,同时每次调用res响应方法后都加return终止后续代码执行。
修复后代码示例:
const { promisify } = require('util'); // 将callback形式的数据库查询转为promise形式,方便使用await const query = promisify(connection.query).bind(connection); /* signup err code: 0 stand for no errors, 1 stand for confirmPassword and password not match 2 stand for user already exist */ app.post('/signup', async (req, res) => { try { // 新增let声明,避免污染全局变量 let signupErr = 0; let username = req.body.username; let email = req.body.email; let password = req.body.password; let confirmPassword = req.body.confirmPassword; let organization = req.body.organization; // 密码校验不通过直接return终止后续逻辑 if (password != confirmPassword){ signupErr = 1; return res.redirect('/signup'); } // 校验邮箱是否存在,用await等待查询结果返回后再执行后续逻辑 const emailCheckRes = await query("SELECT email FROM User WHERE Email = ?", [email]); if(emailCheckRes.length != 0) { signupErr = 2; return res.redirect('/signup'); } // 校验用户名是否存在 const usernameCheckRes = await query("SELECT password FROM User WHERE Username = ?", [username]); if(usernameCheckRes.length != 0) { signupErr = 2; return res.redirect('/signup'); } // 所有校验通过后才执行插入操作 await query("INSERT INTO `PIA`.`User` (`Username`, `Email`, `Password`,`Organization`) VALUES (?,?,?,?)", [username, email, password, organization]); console.log("Inserted"); return res.render('main'); } catch (err) { console.log("操作错误: " + err); return res.redirect('/signup'); } });
如果不想改用async/await,也可以将后续逻辑都嵌套到前一个查询的回调函数中,同时每一步res操作前都加return,但这种写法会形成多层回调嵌套,可读性和可维护性都比较差,更推荐上面的async/await方案。
内容的提问来源于stack exchange,提问作者Stevetian1227
相关产品推荐
相关产品推荐

