ReactJS SignalR .NET:调用SendRequest仅收一次信号,需每次driverReq更新都接收
问题分析与解决方案
核心问题
当前实现仅在客户端调用SendRequest时推送一次数据,未监听driverReq的后续更新并主动推送;同时后端存在异步调用未等待的问题,可能导致推送数据异常。
后端修复步骤
- 修正异步调用等待逻辑
原代码中_mediator.Send(driverReq)未使用await,导致res是Task对象而非实际处理结果,需添加await确保拿到正确数据:
public async Task SendRequest(DriverReqRequest driverReq) { var res = await _mediator.Send(driverReq); await Clients.Client(Context.ConnectionId).SendAsync("broadcastTripList", res); }
- 添加
driverReq更新监听与主动推送
要实现更新时自动推送,需监听driverReq的变更事件(比如领域事件、数据库变更通知),当变更发生时主动推送给客户端。示例如下:
public class TripListHub : Hub, IDisposable { private readonly IMediator _mediator; private readonly IDriverReqUpdateNotifier _updateNotifier; public TripListHub(IMediator mediator, IDriverReqUpdateNotifier updateNotifier) { _mediator = mediator; _updateNotifier = updateNotifier; // 订阅driverReq更新事件 _updateNotifier.DriverReqUpdated += OnDriverReqUpdated; } public async Task SendRequest(DriverReqRequest driverReq) { var res = await _mediator.Send(driverReq); await Clients.Client(Context.ConnectionId).SendAsync("broadcastTripList", res); } private async void OnDriverReqUpdated(object sender, DriverReqUpdatedEventArgs e) { // 推送给当前连接的客户端(需推送给所有客户端则改用Clients.All) await Clients.Client(Context.ConnectionId).SendAsync("broadcastTripList", e.UpdatedDriverReq); } public void Dispose() { // 取消订阅避免内存泄漏 _updateNotifier.DriverReqUpdated -= OnDriverReqUpdated; } }
其中IDriverReqUpdateNotifier是自定义通知服务,需在driverReq更新的业务逻辑中触发对应的更新事件。
前端优化建议
- 避免重复注册监听
当前useEffect依赖connection,每次创建新连接会重复注册监听,建议调整逻辑确保监听只注册一次:
useEffect(() => { if (!connection) return; const startAndListen = async () => { try { await connection.start(); // 先移除旧监听再添加新的,避免重复触发 connection.off("broadcastTripList"); connection.on("broadcastTripList", (signal) => { console.log(signal, "signal"); // 这里可更新组件状态,比如setDriverReq(signal) }); } catch (e) { console.log("Connection failed: ", e); } }; startAndListen(); // 组件卸载时清理连接与监听 return () => { if (connection) { connection.off("broadcastTripList"); connection.stop(); } }; }, [connection]);
- 确保调用
SendRequest时连接就绪
调用invoke前检查连接状态,避免在未连接时发起请求:
const sendRequest = async (data) => { if (!connection || connection.state !== HubConnectionState.Connected) { console.log("Connection not ready"); return; } try { await connection.invoke("SendRequest", { locationModel: data }); console.log("done"); } catch (err) { console.log(err.message); } };
内容的提问来源于stack exchange,提问作者Maryam
相关产品推荐
相关产品推荐

