当用户离开页面时,断开用户与 SignalR 中心的连接

Disconnect User from SignalR Hub when the User Navigates away from the page

提问人:techno 提问时间:11/14/2023 更新时间:11/14/2023 访问量:29

问:

我有以下 SignalRHub

 public class EODStatusHub : Hub    {
       
        public override Task OnConnectedAsync()
        {
            UserHandler.ConnectedIds.Add(Context.ConnectionId);
            return base.OnConnectedAsync();
        }

        public override Task OnDisconnectedAsync(Exception exception)
        {
            UserHandler.ConnectedIds.Remove(Context.ConnectionId);
            return base.OnDisconnectedAsync(exception);
        }
    }

 public static class UserHandler
    {
        public static HashSet<string> ConnectedIds = new HashSet<string>();
    }

我有一个后台服务,它每 5 秒从 API 获取一次数据,具体取决于是否有客户端连接到 Hub

public class TimedEODService : BackgroundService
    {
     
        private readonly ILogger<TimedEODService> _logger;
        private readonly IHubContext<EODStatusHub> _eodStatusHubContext;
        private readonly IEODService _eodService;

        public TimedEODService( ILogger<TimedEODService> logger, IHubContext<EODStatusHub> eodStatusHubContext, IEODService eodService)
        {
            _logger = logger;
            _eodStatusHubContext = eodStatusHubContext;
            _eodService = eodService;

        }


        protected override async Task ExecuteAsync(CancellationToken token)
        {
            await Task.Yield();

            while (token.IsCancellationRequested == false)
            {
                await Task.Delay(5000, token);
                if (UserHandler.ConnectedIds.Count > 0)
                {
                    StatusReport eodStatus = await _eodService.GetEODStatus();
                    _eodStatusHubContext.Clients.All.SendAsync("eodReceived",eodStatus);
                }
            }
        }
    }

连接器的 UI TypeScript 代码

import * as signalR from "@microsoft/signalr";
const URL = "https://localhost:7082/pochub"; //or whatever your backend port is
class Connector {
    private connection: signalR.HubConnection;
    public events: (onMessageReceived: ( message: any) => void) => void;
    static instance: Connector;
    constructor() {
        this.connection = new signalR.HubConnectionBuilder()
            .withUrl(URL)
            .withAutomaticReconnect()
            .build();
        this.connection.start().catch(err => document.write(err));
        this.events = (onMessageReceived) => {
            this.connection.on("eodReceived", ( message) => {
                onMessageReceived(message);
            });
        };
    }
    public newMessage = (messages: string) => {
        this.connection.send("newMessage", "foo", messages).then(x => console.log("sent"))
    }
    public static getInstance(): Connector {
        if (!Connector.instance)
            Connector.instance = new Connector();
        return Connector.instance;
    }
}
export default Connector.getInstance;

当用户在页面上时,我需要建立连接并每 5 秒进行一次 API 调用。这工作正常,但用户在离开页面时不会断开连接。无论用户是否在页面中,都会每 5 秒调用一次 API。

这是 UI 页面的样子

const EODStatus = () => {
     const { newMessage, events } = Connector();
     const [message, setMessage] = useState("initial value");   
     const initialRender = useRef<boolean>(false);    
            useEffect(() => {      
                events((message) => setMessage(message));
            }, []);
           return (
           <>   
    <span>message from signalR: <span style={{ color: "green" }}>{JSON.stringify(message)} 
       </span>
       </>
    }
TypeScript React-Native ASP.Net-Core SignalR

评论

0赞 sommmen 11/14/2023
不确定 react,但在 angular 中,当您的组件被创建/删除时,您有生命周期钩子 - 谷歌搜索将我带到了卸载,也许您可以使用它?retool.com/blog/the-react-lifecycle-methods-and-hooks-explained
0赞 techno 11/14/2023
@sommmen 组件声明为常量。不知道生命周期钩子是否有效。
0赞 poke 11/14/2023
也许有关客户端断开连接方案的文档对您有所帮助。
0赞 Jason Pan 11/14/2023
您可以考虑将事件侦听器添加到组件的钩子中。visibilitychangeuseEffect

答: 暂无答案