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

React Native集成SignalR时,connection.start回调外部调用proxy.invoke报错的问题求助

解决React Native中SignalR后续调用invoke报错的问题

你遇到的问题核心是SignalR连接/代理的作用域管理以及调用前未检查连接状态:在connection.start().done()内部调用时,连接处于完全初始化状态,但后续按钮点击时,要么你的proxy变量因是局部变量已失效,要么连接可能已断开却未做处理。

下面是具体的解决方案和代码重构:

1. 将Connection和Proxy挂载到组件实例上

之前你在componentDidMount里用了局部变量const connection和proxy,这些变量仅在componentDidMount执行周期内有效,后续组件方法无法访问到正确的连接实例。需要把它们绑定到组件的this对象上,确保全局可访问。

2. 封装连接逻辑,添加连接状态检查

调用invoke方法前,先确认连接是否处于活跃状态;如果断开则尝试重新连接,避免直接调用导致报错。

修改后的完整代码示例

componentDidMount() {
  // 将connection和proxy绑定到组件实例,确保全局可访问
  this.connection = signalr.hubConnection(url); 
  // this.connection.logging = true;
  this.proxy = this.connection.createHubProxy("mobileStockTickerHub");

  // 监听服务器推送的消息
  this.proxy.on("msgreceived", (msg) => { 
    this.setState({ randomdata: msg }); 
  });

  // 连接状态相关监听
  this.connection.connectionSlow(() => {
    console.log("We are currently experiencing difficulties with the connection.");
  });

  this.connection.error((error) => {
    const errorMessage = error.message;
    let detailedError = "";
    if (error.source && error.source._response) {
        detailedError = error.source._response;
    }
    if (detailedError === "An SSL error has occurred and a secure connection to the server cannot be made.") {
        console.log("When using react-native-signalr on ios with http remember to enable http in App Transport Security");
    }
    console.debug("SignalR error: " + errorMessage, detailedError);
  });

  // 初始化连接
  this.startSignalRConnection();
}

// 封装连接启动方法,方便复用
startSignalRConnection = () => {
  return this.connection
    .start()
    .done(() => {
        console.log("Now connected, connection ID=" + this.connection.id);
        // 连接成功后执行初始化操作
        this.proxy
          .invoke("setUserName", "Hemal")
          .done((directResponse) => {
              console.log("direct-response-from-server", directResponse);
          })
          .fail(() => {
              console.warn("Something went wrong when calling server, it might not be up and running?");
          });
    })
    .fail(() => {
        console.log("Failed to connect to SignalR hub");
    });
}

// 按钮点击触发的订阅方法
handleSubscribeToSymbols = () => {
  // 先检查连接是否处于活跃状态
  if (this.connection.state !== signalr.connectionState.connected) {
    console.log("Connection not active, attempting to reconnect...");
    // 重新连接成功后再执行订阅
    this.startSignalRConnection().done(() => {
      this.executeSubscription();
    }).fail(() => {
      console.warn("Could not reconnect, cannot complete subscription");
    });
    return;
  }

  // 连接正常,直接执行订阅
  this.executeSubscription();
}

// 封装实际的订阅调用逻辑
executeSubscription = () => {
  this.proxy.invoke("subscribeToSymbols", "123")
    .done(() => {
      console.log("Successfully subscribed to symbol 123");
    })
    .fail((error) => {
      console.warn("Failed to subscribe to symbol:", error);
    });
}

// 组件卸载时关闭连接,避免内存泄漏
componentWillUnmount() {
  if (this.connection && this.connection.state === signalr.connectionState.connected) {
    this.connection.stop();
    console.log("SignalR connection closed");
  }
}

关键说明

  • 作用域管理:通过this.connection和this.proxy保存实例,确保组件所有方法都能访问到同一个SignalR连接和代理。
  • 连接状态检查:调用任何invoke方法前,先判断connection.state是否为connected,如果不是则重新连接。
  • 代码复用:把连接启动和实际调用逻辑封装成独立方法,避免重复代码,也方便维护。
  • 内存泄漏防护:在componentWillUnmount中关闭连接,避免组件卸载后SignalR还保持连接占用资源。

如果希望连接断开后自动重连,可以在connection.disconnected事件中添加重连逻辑:

this.connection.disconnected(() => {
  console.log("SignalR disconnected, attempting to reconnect in 3 seconds...");
  setTimeout(() => {
    this.startSignalRConnection();
  }, 3000);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:17:36