Sequelize中find查询promise内创建实例报ERR_HTTP_HEADERS_SENT如何解决
问题根因
- 核心报错是因为一个请求触发了两次HTTP响应发送:密码校验通过后,你先发起了异步的
Token.create数据库操作,没有等它完成就直接执行了res.status(200).json({message : "ok", token : token})发送了第一次响应;等Token.create的then/catch回调执行时,又尝试第二次发送响应,此时响应头已经被发送到客户端,就会抛出ERR_HTTP_HEADERS_SENT错误。 - 你之前把Token创建逻辑移到find查询块外会报token未定义,是因为token是在用户存在、密码校验通过后才生成的变量,本身作用域就局限在findOne的回调逻辑里,移到外面自然找不到该变量,不需要调整位置,只要改响应发送逻辑即可。
- 额外语法问题:
expired_at的赋值写法错误,sequelize.col(sequelize.fn('NOW'))属于多余嵌套,直接调用sequelize.fn('NOW')即可。
修复代码
方案1:调整原有then链逻辑
删除异步操作外的冗余响应发送,所有返回逻辑都放到Token.create的回调中:
exports.authenticate = (req, res) => { const credentials = req.body; User.findOne({ where : { email : req.body.login } }) .then((user) => { if (!user) { console.log('notfound!') return res.status(404).send("user not found"); } if (!bcrypt.compareSync(req.body.password, user.password)){ return res.status(403).send('wrong password') } // 密码校验通过,生成token并存库 const token = jwt.sign({username : user.username}, secret.secret, {expiresIn : "2 days"}); Token.create({ code : token, expired_at : sequelize.fn("DATEADD", sequelize.literal("day"), 2, sequelize.fn('NOW')) }).then((tkn) => { console.log(tkn); // 存库成功后再返回响应 return res.status(200).json(tkn.toJSON()); }).catch((e) => { console.log(e); return res.status(500).json({"message": "Server Error"}); }); }) .catch((e) => { console.log(e); res.status(500).send('unhandled Server error'); }); }
注意在每个res返回前加return,避免后续多余逻辑执行。
方案2:用async/await改写(更推荐,逻辑更清晰)
用同步写法的逻辑处理异步操作,避免回调嵌套:
exports.authenticate = async (req, res) => { try { const user = await User.findOne({ where : { email : req.body.login } }) if (!user) { console.log('notfound!') return res.status(404).send("user not found"); } if (!bcrypt.compareSync(req.body.password, user.password)){ return res.status(403).send('wrong password') } const token = jwt.sign({username : user.username}, secret.secret, {expiresIn : "2 days"}); const tkn = await Token.create({ code : token, expired_at : sequelize.fn("DATEADD", sequelize.literal("day"), 2, sequelize.fn('NOW')) }) console.log(tkn); return res.status(200).json(tkn.toJSON()); } catch(e) { console.log(e); return res.status(500).json({"message": "Server Error"}); } }
内容的提问来源于stack exchange,提问作者Majd
相关产品推荐
相关产品推荐

