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
相关产品推荐
相关产品推荐

