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

基于React.js与SignalR实现推送通知:连接成功但收不到消息排查

SignalR 推送通知无法接收的问题排查与修复

代码中存在的核心问题

  • 模板字符串解析错误:withUrl中用单引号包裹包含${userId}的URL,导致userId未被正确注入,Hub无法识别当前用户,进而无法推送对应消息。
  • 重复传递Query参数:URL末尾已拼接?userId=${userId},同时又在options里设置queryString: userId=${userId},参数重复可能引发Hub端解析异常。
  • 无效的Connection存储:localStorage.setItem('signalrConnection',JSON.stringify(connection))完全无效,SignalR连接对象包含函数、循环引用和内部状态,无法被JSON序列化,存入后无法复用。
  • 事件监听时机不合理:虽然后续绑定监听也能工作,但建议在connection.start()之前绑定事件,避免错过连接成功后立即推送的消息。
  • 缺乏认证Token传递:仅靠userId参数无法保证身份合法性,若Hub需要认证,应将JWT Token放入请求头,否则Hub可能拒绝处理或无法正确识别用户。
  • 重连状态未处理:开启了withAutomaticReconnect()但未监听重连相关事件,无法知晓连接是否断开或重连成功,不利于问题排查。

修复后的完整代码

import { HubConnectionBuilder, HttpTransportType } from '@microsoft/signalr';
import jwt_decode from "jwt-decode";

let connection = null;

export function setupSignalRConnection(onNotificationReceived ) {
  const token = localStorage.getItem("token");
  let userId = "";
  let authToken = null;

  if (token) {
    const decodedToken = jwt_decode(token);
    userId = decodedToken.UserId;
    authToken = token;
    console.log('Current user ID:', userId);
  }

  // 避免重复创建连接
  if (connection?.state === 'Connected' || connection?.state === 'Connecting') {
    return connection;
  }

  connection = new HubConnectionBuilder()
    .withUrl('http://123.456.789.365/ExampleURL/NotificationUserHub', {
      transport: HttpTransportType.WebSockets, // 明确指定WebSocket传输
      timeout: 30000, // 缩短超时时间,默认30秒足够,原50分钟设置不合理
      queryString: `userId=${userId}`,
      // 添加认证头,确保Hub能验证用户身份
      headers: {
        Authorization: `Bearer ${authToken}`
      }
    })
    .withAutomaticReconnect([0, 2000, 10000, 30000]) // 自定义重连间隔
    .build();

  // 提前注册事件监听
  connection.on("sendToParent", (notification) => {
    console.log('Received parent notification:', notification);
    onNotificationReceived(notification);
  });

  connection.on("sendToEmployee", (notification) => {
    console.log('Received employee notification:', notification);
    onNotificationReceived(notification);
  });

  // 监听连接状态变化
  connection.onreconnecting((error) => {
    console.log('Reconnecting to SignalR hub...', error);
  });

  connection.onreconnected((connectionId) => {
    console.log('Reconnected to SignalR hub. New connection ID:', connectionId);
  });

  connection.onclose((error) => {
    console.log('SignalR connection closed:', error);
    connection = null; // 连接关闭后重置,下次调用会重新创建
  });

  connection.start()
    .then(() => {
      console.log('Connected to SignalR hub. Connection ID:', connection.connectionId);
    })
    .catch(error => {
      console.error('SignalR connection failed:', error);
      connection = null;
    });

  return connection;
}

额外验证建议

  • 检查Hub端用户映射逻辑:确认Hub端是否正确通过userId参数将连接与用户关联,比如使用Groups.AddToGroupAsync(connectionId, userId),或推送时指定正确的用户/组。
  • 验证推送目标匹配:确保后端触发推送时,调用的方法名(sendToParent/sendToEmployee)与前端监听的完全一致,SignalR方法名大小写敏感。
  • 浏览器控制台排查:打开DevTools的Network标签,查看WebSocket连接的帧,确认后端是否真的推送了消息;查看Console标签,是否有未捕获的错误。
  • 跨域问题检查:若前端与Hub不在同一域名,确认后端已配置正确的CORS策略,允许WebSocket连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:05:32