如何使用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
相关产品推荐
相关产品推荐

