What is the correct JavaScript pattern to connect to SignalR and maintain the link perpetually while they are on the page, no matter if people hibernate their computers or have spotty internet connections.
The documentation just says use:
$.connection.hub.start()
.done(function(){ console.log('Now connected, connection ID=' + $.connection.hub.id); })
.fail(function(){ console.log('Could not Connect!'); });
});
But this does not seem to take disconnects and other issues into account.
Also, it doesn't catch the problem of the session expire and requires re-login.
Given that SignalR is a connection based client/server solution, you cannot have expectations of long sustained open connections. So as Kelso Sharp wrote in his answer, the only good thing you can do is manage the events of the connection life cycle.
Check out the documentation for all the life cycle events of a signalR connection: https://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#connectionlifetime
So if we do not focus our attention on how to make a persistent connection that never fails, we could instead focus on giving the user an impression of that, by cunningly managing the disconnects, reloads and such in the background.
Here is a diagram showing how I would setup this, even though you do not specify what causes your hub to push data out to clients, but I imaging it could be something like this diagram. The idea here is that you push the same state to some kind of state provider - i.e. cache, web api storage, so that you have the entire set of data available at any given time. When ui loads or disconnects, it should issue a request to this provider to regain state, and then it should reconnect to the hub.
If data consistency is a issue, you could do versioning of the state, keep a local copy in the ui, and then do an audit upon reconnecting. That way you could see if you missed out on something, in which case you would issue catch up requests to the state provider.
To handle the events you just have hook in some functions on your client side: //this will trigger for all state changes during the connection cycle:
$.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.reconnecting) {
console.log("liveFeed is reconnecting!");
}
else if (change.newState === $.signalR.connectionState.connected) {
console.log("liveFeed is connected!");
}
});
//this triggers when the disconnecting to the hub.
$.connection.hub.disconnected(function () {
console.log('Connection disconnected')
});
The only way that I that I think this can be done is to use a backplane that stores connection info of each connected client. That said, they will never "Stay Connected" If they lost internet or hibernate, all that you can do is "reconnect" You will have to store any state information on a continual basis in the event of a disconnection, you cannot do this in the "disconnect" event because by then it is likely too late. One option would be to continually stream state info to a redis cache and periodically send it to that the back plane in more reasonable intervals, or when the disconnected even fires.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With