MEAN演示应用集成JWT后新增消息致服务器崩溃问题排查
问题诊断与修复方案
看起来你的核心问题是消息创建时的用户保存操作未处理错误,导致服务器触发未捕获异常直接崩溃——这就是为什么消息能成功写入MongoDB,但请求会返回net::ERR_CONNECTION_RESET的原因。
核心问题分析
在router.post('/')的代码里,你执行user.save()时没有添加错误处理回调:
user.save(); // 这里遗漏了错误处理!
当用户文档保存失败(比如MongoDB验证错误、连接波动等),Node.js会抛出未捕获的异常,直接终止服务器进程,所以客户端收到了连接重置的错误。
另外还有一个可以优化的点:你在每个需要认证的路由里重复调用jwt.decode(),其实可以在JWT验证中间件里把解码后的用户信息挂载到req对象上,避免重复操作,也更安全(毕竟中间件已经验证过token的有效性)。
修复后的代码
1. 优化JWT验证中间件
把解码后的用户信息存到req.user里,后续路由直接复用:
router.use('/', (req, res, next) => { jwt.verify(req.query.token, 'secret', (err, decoded) => { if (err) { return res.status(401).json({ title: 'Not Authenticated', error: err }); } // 将解码后的用户信息挂载到req对象,供后续路由使用 req.user = decoded.user; next(); }) });
2. 修复消息创建路由,添加错误处理
修改router.post('/'),给user.save()添加错误回调,同时用req.user替代重复解码:
router.post('/', (req, res, next) => { User.findById(req.user._id, (err, user) => { if (err) { return res.status(500).json({ title: 'An error occurred', error: err }); } let message = new Message({ content: req.body.content, user: user }); message.save((err, result) => { if (err) { return res.status(500).json({ title: 'An error occurred', error: err }); } user.messages.push(result); // 新增用户保存的错误处理回调 user.save((err) => { if (err) { return res.status(500).json({ title: 'Failed to update user', error: err }); } res.status(201).json({ message: 'Saved message', obj: result }); }); }); }); });
额外优化建议
为了避免回调地狱,让代码更易读和维护,建议改用async/await语法:
router.post('/', async (req, res, next) => { try { const user = await User.findById(req.user._id); if (!user) { return res.status(404).json({ title: 'User not found', error: { message: 'User does not exist' } }); } // 直接存用户ID而非整个对象,MongoDB populate只需要ID就能关联查询 const message = new Message({ content: req.body.content, user: user._id }); const savedMessage = await message.save(); user.messages.push(savedMessage._id); await user.save(); res.status(201).json({ message: 'Saved message', obj: savedMessage }); } catch (err) { res.status(500).json({ title: 'An error occurred', error: err }); } });
验证修复
完成修改后重启服务器,尝试创建消息:
- 即使用户保存过程中出现错误,服务器会返回500错误而非崩溃
- 客户端不会再收到
net::ERR_CONNECTION_RESET提示
内容的提问来源于stack exchange,提问作者Raffy
相关产品推荐
相关产品推荐

