这个问题最好由未来的通道消息规范解决,该规范迄今为止尚未被任何浏览器实现,但我设法通过限制Alex Ford 描述的连接数量并localStorage
用作选项卡之间的消息总线来解决它.
该storage
事件允许您在选项卡之间传播数据,同时保持单个 SignalR 连接打开(从而防止连接饱和)。调用将在所有其他选项卡(不是调用者)中localStorage.setItem('sharedKey', sharedData)
引发事件:storage
$(window).bind('storage', function (e) {
var sharedData = localStorage.getItem('sharedKey');
if (sharedData !== null)
console.log(
'A tab called localStorage.setItem("sharedData",'+sharedData+')'
);
});
您可以测试if ($.connection.hub.state === 1)
以确定给定选项卡是否应通过 localStorage(由 Alex 提供)通知其他选项卡,以防止重复localStorage.setItem
调用。
Facebook 通过在多个子域上提供持久连接来克服浏览器的限制,但这会使部署和测试复杂化。
注意事项
旧连接:在 Alex 的解决方案中,您需要小心Disconnect()
不要被调用(例如异常),并且您需要HubConnections
用旧的集线器连接填充您的存储桶(或存储库)。如果会话 ID 没有更改(可能发生),这可能会阻止新客户端建立 SignalR 连接,即使没有处于活动状态。或者,为新连接添加时间戳并设置一个滑动过期时间以最大限度地减少潜在影响。
锁定: localStorage
可能会受到竞争条件的影响,因为它没有实现此处描述的任何锁定。
为了支持不同类型的事件,您应该在 JSON 消息中编码一个eventType并在storage
事件上对其进行测试。
后备
如果无法建立 SignalR 连接,我会每 45 秒轮询一次服务器以检索通知计数。
如果不想使用localStorage,可以使用cookies,但不是那么干净。