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

基于React+Express的聊天应用SSE消息无法跨Tab显示问题求助

解决SSE多标签页无法接收消息的问题

问题根源

你的代码里,服务器仅维护了SSE客户端连接列表,但当新消息创建时,没有将消息广播给所有已连接的SSE客户端;同时客户端在发送消息后主动调用fetchMessages拉取全量消息,没有完全利用SSE的推送能力,导致其他标签页无法实时同步新消息。


解决方案

1. 服务器端修改:新增消息广播逻辑

在POST /messages接口中,当消息成功存入数据库后,遍历所有SSE客户端连接,将新消息推送给每个客户端。

修改后的Server.js关键代码:

// 补充POST /messages接口的广播逻辑
app.post('/api/messages', async (req, res) => {
  try {
    const newMessage = await prisma.message.create({
      data: req.body
    });
    
    // 广播新消息给所有SSE客户端
    sseClients.forEach(client => {
      // 遵循SSE格式:指定事件类型+JSON数据
      client.write(`event: message\n`);
      client.write(`data: ${JSON.stringify({
        event: 'message',
        data: newMessage
      })}\n\n`);
      // 强制刷新响应,确保消息即时发送
      client.flush();
    });
    
    res.status(201).json(newMessage);
  } catch (error) {
    res.status(500).json({ error: 'Failed to create message' });
  }
});

若你的Express版本不支持client.flush(),可安装express-flush中间件启用该功能。

2. 客户端修改:移除冗余拉取,依赖SSE推送更新

客户端发送消息后,无需调用fetchMessages拉取全量列表,直接通过SSE推送的消息更新状态,避免重复请求的同时确保多标签页同步。

修改后的Chat.js关键代码:

// 修改handleAddMessage函数,移除全量拉取逻辑
const handleAddMessage = async ({ name, message }) => {
  try {
    await instance.post('/messages', { name, message });
    // 删除原有的fetchMessages()调用
  } catch (error) {
    console.error('Error adding message:', error);
  }
};

// 简化useEffect的依赖项
useEffect(() => {
  const eventSource = new EventSource('http://localhost:3001/api/sse');

  fetchMessages();

  eventSource.onopen = (event) => {
    console.log('EventSource connected successfully');
  };

  eventSource.addEventListener('message', (event) => {
    console.log('Received SSE event:', event);
    const eventData = JSON.parse(event.data);

    if (eventData.event === 'message') {
      console.log('Received SSE message:', eventData.data);
      setMessages((prevMessages) => [...prevMessages, eventData.data]);
    }
  });

  eventSource.addEventListener('error', (error) => {
    console.error('EventSource failed:', error);
    eventSource.close();
  });

  return () => {
    eventSource.close();
  };
}, []); // 依赖项改为空数组,因为fetchMessages和setMessages都是稳定函数

验证效果

重启服务器后,打开多个浏览器标签页进入聊天页面,在任意标签页发送消息,所有标签页都会通过SSE实时收到新消息并更新列表。

内容的提问来源于stack exchange,提问作者Clay.Lente

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:37:08