ASP.NET Core 3.1 SignalR偶发无法向React应用返回数据如何解决
核心问题修复方案
1. 前端事件注册时序错误(主要诱因)
你当前的代码是先启动SignalR连接,再注册ShowMainLobby事件监听。当连接建立速度较快时,服务端OnConnectedAsync会在事件注册完成前就推送消息,导致前端漏收,多次操作后稳定复现加载卡住的问题。
修复后的React核心逻辑:
useEffect(() => { if (conn) { // 先注册事件,再启动连接 conn.on("ShowMainLobby", (tournaments) => { setTournaments(tournaments); console.log(tournaments); setScreen("ShowMainLobby"); }); conn.start() .then((result) => { console.log("Connected"); }) .catch((ex) => console.log("connection Failed: ", ex)); } // 组件卸载时清理连接和事件,避免内存泄漏 return () => { if (conn) { conn.off("ShowMainLobby"); conn.stop(); } } }, [conn]);
2. 服务端增加异常捕获与异步优化
服务端OnConnectedAsync未做异常捕获,一旦_tournamentsStore查询、AutoMapper映射、序列化任意环节出错,会直接中断推送,前端无任何反馈:
public override async Task OnConnectedAsync() { try { await Groups.AddToGroupAsync(Context.ConnectionId, "Not playing"); // 建议把GetAvailableTournaments改成异步方法,避免阻塞Hub线程 var availableTournaments = _tournamentsStore.GetAvailableTournaments(); var availableTournamentsDto = _mapper.Map<List<TournamentDto>>(availableTournaments); await Clients.Caller.ShowMainLobby(availableTournamentsDto); await base.OnConnectedAsync(); } catch (Exception ex) { // 这里打日志排查具体错误,比如DTO序列化循环引用、存储查询超时等 _logger.LogError(ex, "推送锦标赛列表失败,连接ID:{ConnectionId}", Context.ConnectionId); throw; } }
3. 可选补充配置
如果服务端日志提示序列化错误,需要在Program.cs/Startup.cs中配置SignalR的System.Text.Json序列化规则,忽略循环引用:
services.AddSignalR() .AddJsonProtocol(options => { options.PayloadSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; });
内容的提问来源于stack exchange,提问作者Hrvoje Brešić
相关产品推荐
相关产品推荐

