Node.js电商项目:Admin端通知数动态更新中间件故障排查
问题分析与解决方案
一、现有代码的潜在问题
- 中间件挂载顺序错误:Express中间件按注册顺序执行,如果这个中间件是在具体admin路由(比如
admin_route.get('/dashboard', ...))之后挂载的,根本不会触发。必须把它放在所有admin路由定义之前。 - 错误处理缺失异常传递:catch块只打印错误但没调用
next(error),一旦数据库查询出错,后续路由会卡住,且无法触发全局错误处理逻辑。 - 未做管理员身份校验:所有访问admin_route的请求都会执行查询,包括非管理员用户,既浪费资源也有数据泄露风险。
- 查询写法冗余:
find().countDocuments()可以简化为直接调用countDocuments(),减少一次查询构建开销。
二、修复后的中间件代码
// 务必将此中间件放在所有admin路由定义之前 admin_route.all('*', async (req, res, next) => { // 替换成你的管理员身份校验逻辑 if (!req.user || req.user.role !== 'admin') { return next(); // 非管理员直接跳过 } try { // 简化计数查询 const adminNotificationsCount = await Notifications.countDocuments({ matter: 'returnOrderRequest' }); res.locals.adminNotifications = adminNotificationsCount; next(); } catch (error) { console.error('获取退货申请通知数量失败:', error.message); next(error); // 把错误传递给全局错误处理中间件 } });
三、其他可行实现方案
方案1:缓存优化(减少数据库查询)
如果退货申请不是实时高频更新,可以用内存缓存定时刷新计数,降低数据库压力:
const NodeCache = require('node-cache'); const cache = new NodeCache({ stdTTL: 300 }); // 5分钟自动过期 admin_route.all('*', async (req, res, next) => { if (!req.user || req.user.role !== 'admin') return next(); try { let count = cache.get('return_notifications_count'); if (!count) { count = await Notifications.countDocuments({ matter: 'returnOrderRequest' }); cache.set('return_notifications_count', count); } res.locals.adminNotifications = count; next(); } catch (error) { console.error('获取通知数量失败:', error.message); next(error); } });
方案2:前端异步请求(前后端分离场景)
后端提供单独接口,前端页面加载时主动请求计数:
// 后端接口 admin_route.get('/api/notifications/return-count', async (req, res) => { if (!req.user || req.user.role !== 'admin') { return res.status(403).json({ error: '无权限访问' }); } try { const count = await Notifications.countDocuments({ matter: 'returnOrderRequest' }); res.json({ count }); } catch (error) { res.status(500).json({ error: '获取通知数量失败' }); } });
前端示例(原生JS):
// 页面初始化时调用 async function loadNotificationCount() { try { const res = await fetch('/admin/api/notifications/return-count'); const data = await res.json(); document.getElementById('notification-count').textContent = data.count; } catch (err) { console.error('加载通知数量失败:', err); } } loadNotificationCount();
四、快速排查步骤
- 打开注释的
console.log('Middleware executed');,看请求时控制台是否输出,判断中间件是否被触发。 - 检查
admin_route的挂载顺序,确保此中间件在所有具体admin路由之前。 - 直接在MongoDB Shell执行
db.notifications.countDocuments({ matter: 'returnOrderRequest' }),验证查询是否能返回正确结果。 - 检查数据库连接状态,确认服务有权限访问
Notifications集合。
内容的提问来源于stack exchange,提问作者Afsal
相关产品推荐
相关产品推荐

