Postman请求Node异步路由返回Cannot GET及响应头重复设置报错问题
问题根因
你的错误完全来自validateToken中间件的错误写法,和MongoDB/Mongoose无关:
- 中间件末尾有一个全局的
next()调用,没有放在任何逻辑分支内。jwt.verify是异步执行的,代码运行时会先触发这个全局next(),提前进入路由处理逻辑,此时req.decodedJwt还未赋值,路由中访问req.decodedJwt.username会直接抛出未定义错误,触发框架默认错误响应,HTTP头已经被发送。 - 等
jwt.verify异步回调执行完成后,要么会返回401响应,要么会再次调用next()执行路由逻辑,此时再次尝试发送响应就会触发Cannot set headers after they are sent to the client报错。 - 路由代码中
console.log(query)的query变量未定义,也会额外抛出未捕获异常。
修复方案
1. 修复validateToken中间件
删除末尾多余的next(),所有返回响应的分支添加return避免后续代码执行:
module.exports = (req, res, next) => { const token = req.headers.authorization; if (token) { jwt.verify(token, jwtSecret, (err, decoded) => { if (err) { console.log("\n!!!~~~Sending response~~~!!!\n") return res.status(401).json('Please supply a valid token') } req.decodedJwt = decoded; next(); }) } else { console.log("\n!!!~~~Sending response~~~!!!\n") return res.status(401).json("You must have a token to do that"); } }
2. 修复路由代码
删除未定义的query变量打印,因为你的Schema中username是唯一值,建议用findOne替代find减少不必要的返回:
router.get('/fetch', validateToken, async (req, res) => { try { const user = req.decodedJwt.username; const data = await Todo.findOne({username: user}); res.json(data) } catch (err) { console.log(err) res.status(500).json(err) } })
内容的提问来源于stack exchange,提问作者Archa9
相关产品推荐
相关产品推荐

