Javascript 选项卡同步和服务器事件

Javascript tabs synchronization and server events

我的申请需要一些帮助,对不起我的英语。

我从事网站的前端工作。最终的应用程序应该可以很好地处理大量选项卡(在单个浏览器中 ~100)。每个选项卡都需要侦听从服务器发送的一系列事件并动态更改其内容。

我使用 Websocket 实现了这个功能。因为打开一个连接是非常昂贵的。所以我分配了一个主选项卡,它将监听来自服务器的事件并使用 BroadcastChannel 将它们分发到其他选项卡。我有以下问题:


How to pick a master tab from all of them and make other tabs listen to it?

我有这些想法:

1。使用广播频道。

在初始化选项卡中使用 BroadcastChannel 询问:"is there a master tab?"。如果收到答复,它将继续工作。如果它没有收到任何响应,那么它将自己设为主选项卡。

问题:

如果 master tab 会在重循环内冻结,那么它会在短时间内无法响应,导致与服务器打开 2 个连接并发生冲突,需要解决。

2。使用本地存储。

在初始化期间,选项卡将请求一些名为“X或 smth 的字段。如果字段为空,则选项卡将创建该字段并分配一些值,然后它将自己设为主选项卡。如果字段“X”不为空,则选项卡将使自己成为从属选项卡。

问题:

如果两个选项卡同时初始化,可能会发生冲突:

tab_Alpha -> localStorage.getItem("haveMaster") -> undefined // There is no master, so i will make myself a master tab!
tab_Beta  -> localStorage.getItem("haveMaster") -> undefined // There is no master, so i will make myself a master tab!

tab_Alpha -> localStorage.setItem("haveMaster", true) // Now it's time to open connection and listen for events
tab_Beta  -> localStorage.setItem("haveMaster", true) // Now it's time to open connection and listen for events

结果,我有一个冲突和两个打开的连接。


有人能给我指出一个轻量级的解决方案吗?我将不胜感激。


经过研究

Halcyon 建议使用 gist.github.com/neilj/4146038 中的代码。但我对这个解决方案并不满意,因为如果 Math.random() 将 return 2 个相同的数字用于 2 个不同的选项卡,当它们初始化时,浏览器将调用 masterDidChange() 两次。浏览器最终会出现冲突和 2 个连接。

然后 Dimitry Boger 建议阅读此内容:alpha.de/2012/03/javascript-concurrency-and-locking-the-html5-localstorage
我更喜欢这个解决方案,但我仍然设法找到破解它的方法。
如果每个选项卡将在几个地方冻结,那么它将再次导致执行 criticalSection().

然后我找到了一个wikipedia.org/wiki/Peterson's_algorithm。我还没有找到打破这种锁定机制的方法,但是有一个问题。
为了使该算法起作用,浏览器必须在执行前知道确切的制表符数量。因为如果它会启动一个新标签,那么之前的标签可能会错过这个事件并在新标签完成它自己的标签之前开始他们的 criticalSection()

因此,如果您不害怕 1024 个选项卡同时初始化和冻结它们自己,那么您可以使用这些解决方案中的任何一个。但是我需要一个防弹的,所以我决定把找到主选项卡的荣誉交给后端服务器。

谢谢大家的帮助。


又研究了一下

post下有防弹答案。它可以在没有后端服务器的情况下工作。

我 运行 不久前就遇到过这个问题。我从名为 Overture 的应用程序中找到了这个 windowcontroller.js

它能正确处理竞争条件和超时。

我认为它开箱即用,但我对其进行了一些修改以满足我的需要。

SharedWorker可以解决问题

它将使用专用的阻塞线程来进行自身与其他浏览器上下文之间的所有通信 (tabs/iframes)。所以它可以用来同步不同的东西。

MDN Article about SharedWorker