You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js电商项目:Admin端通知数动态更新中间件故障排查

问题分析与解决方案

一、现有代码的潜在问题

  1. 中间件挂载顺序错误:Express中间件按注册顺序执行,如果这个中间件是在具体admin路由(比如admin_route.get('/dashboard', ...))之后挂载的,根本不会触发。必须把它放在所有admin路由定义之前。
  2. 错误处理缺失异常传递:catch块只打印错误但没调用next(error),一旦数据库查询出错,后续路由会卡住,且无法触发全局错误处理逻辑。
  3. 未做管理员身份校验:所有访问admin_route的请求都会执行查询,包括非管理员用户,既浪费资源也有数据泄露风险。
  4. 查询写法冗余: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();

四、快速排查步骤

  1. 打开注释的console.log('Middleware executed');,看请求时控制台是否输出,判断中间件是否被触发。
  2. 检查admin_route的挂载顺序,确保此中间件在所有具体admin路由之前。
  3. 直接在MongoDB Shell执行db.notifications.countDocuments({ matter: 'returnOrderRequest' }),验证查询是否能返回正确结果。
  4. 检查数据库连接状态,确认服务有权限访问Notifications集合。

内容的提问来源于stack exchange,提问作者Afsal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:17:16