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

如何使用express-sse结合路由用户ID发送初始数据?

解决方案

核心问题是你当前使用了全局SSE实例,无法针对每个请求(每个用户)动态设置初始数据,且init中间件会完成SSE响应的初始化,后续中间件代码大概率不会执行。要实现按用户发送初始通知,需要按请求动态实例化SSE,并在实例化时传入该用户的专属初始数据。

1. 调整SSE模块导出方式

不要全局创建SSE实例,改为导出SSE类,方便在路由中按需实例化:

// sse/index.js
const SSE = require("express-sse");
module.exports = SSE;

2. 重构路由逻辑

在路由中先通过requireAuth获取用户ID,查询该用户的历史通知,再创建SSE实例并传入初始数据,最后调用init完成连接初始化:

const SSE = require('./sse/index');
const Notification = require('./models/Notification'); // 替换为你的通知数据模型

router.get('/notifications_stream', requireAuth, async (req, res) => {
  // 从req.user中获取用户ID(假设requireAuth已将用户信息挂载到req.user)
  const userId = req.user.id;
  
  // 查询数据库,获取该用户的所有历史通知
  const initialNotifications = await Notification.find({ userId }).sort({ createdAt: -1 });
  
  // 针对当前用户实例化SSE,传入专属初始数据
  const sse = new SSE(initialNotifications);
  
  // 初始化SSE连接,自动发送初始数据
  sse.init(req, res);
  
  // 可选:将当前SSE实例存入全局连接池,用于后续给该用户推送实时通知
  // 比如:if (!global.sseConnections) global.sseConnections = new Map();
  // global.sseConnections.set(userId, sse);
});

3. 实时推送新通知

当产品变更需要给特定用户推送通知时,从连接池中取出对应用户的SSE实例调用send即可:

// 产品变更时的通知逻辑示例
async function pushProductNotification(userId, notificationContent) {
  const sse = global.sseConnections?.get(userId);
  if (sse) {
    sse.send(notificationContent);
    // 同时将新通知存入数据库,确保新用户连接时能获取到历史数据
    await Notification.create({ userId, content: notificationContent });
  }
}

为什么之前的方法无效?

  • 全局SSE实例:初始数据固定,无法根据用户动态调整,且send会推送给所有连接用户,不符合精准推送需求。
  • init后的中间件:sse.init会完成SSE响应头发送、初始数据推送等核心操作,后续中间件代码不会被执行,所以send调用无效。
  • 双路由方案:不仅冗余,全局send无法精准定位到当前连接用户,会导致所有用户收到重复数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 00:15:32