连接到SignalR并在页面上永久保持链接的正确JavaScript模式是什么,无论人们是在休眠计算机还是网络连接都不稳定。
文档只是说使用:
$.connection.hub.start()
.done(function(){ console.log('Now connected, connection ID=' + $.connection.hub.id); })
.fail(function(){ console.log('Could not Connect!'); });
});
但这似乎并未将断开连接和其他问题考虑在内。
此外,它无法解决会话过期的问题,需要重新登录。
答案 0 :(得分:2)
鉴于SignalR是基于连接的客户端/服务器解决方案,您不能期望长期持续的开放连接。正如凯尔索夏普在他的回答中所写,唯一可以做的就是管理连接生命周期的事件。
查看signalR连接的所有生命周期事件的文档: https://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#connectionlifetime
因此,如果我们不把注意力集中在如何建立一个永不失败的持久连接上,那么我们可以通过在后台狡猾地管理断开连接,重新加载等来专注于给用户一个印象。
这是一个显示我如何设置它的图表,即使您没有指定导致集线器将数据推送到客户端的原因,但我对它进行成像可能就像这个图。这里的想法是你将相同的状态推送到某种状态提供者 - 即缓存,web api存储,这样你就可以在任何给定的时间获得整套数据。当ui加载或断开连接时,它应该向该提供者发出请求以重新获得状态,然后它应该重新连接到该中心。
如果数据一致性是个问题,您可以对状态进行版本控制,在ui中保留本地副本,然后在重新连接时进行审核。这样你可以看出你是否错过了某些东西,在这种情况下你会向国家提供者发出追赶请求。
要处理您刚刚在客户端的某些功能中挂钩的事件: //这将在连接周期中触发所有状态更改:
$.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!");
}
});
//当断开与集线器连接时触发。
$.connection.hub.disconnected(function () {
console.log('Connection disconnected')
});
答案 1 :(得分:1)
我认为可以做到这一点的唯一方法是使用存储每个连接客户端的连接信息的背板。也就是说,他们永远不会“保持联系”如果他们失去了互联网或休眠,你可以做的就是“重新连接”你必须在断开连接的情况下持续存储任何状态信息,你不能这样做“脱离”事件,因为到那时可能为时已晚。一种选择是不断将状态信息流式传输到redis缓存,并以更合理的间隔周期性地将其发送到背板,或者当断开连接时甚至触发。
答案 2 :(得分:0)
通过重试将所有调用包装到服务器,找出如何使会话过期:
function callServer(call) {
function err(r?: Error) {
var output = $.Deferred();
if (r &&
r.message &&
(r.message.startsWith("Caller is not authorized to invoke the") ||
r.message.startsWith("The user identity cannot change during "))) {
$('#login-dialog')
.one('hide.bs.modal',
() => {
hub.connection.stop();
$.connection.hub.start()
.then(() => hub.server.run(call))
.then(output.resolve, output.reject);
})
.modal('show');
return output;
}
// ReSharper disable once SuspiciousThisUsage
return output.rejectWith(this, <any>arguments);
}
return $.connection.hub.start()
.then(() => hub.server.run(call))
.then(null, err);
}
这假设有一个引导模式对话框#login-dialog
,当关闭时意味着它已经处理了重新登录。