Javascript 如何在Safari 10+;中使用BroadcastChannel API或类似工具;?
问题: 我需要一个客户端Javascript解决方案(jQuery很好),其中一个浏览器窗口/选项卡中的事件可以广播到同一域中的其他窗口/选项卡。例如,如果在选项卡a中更新购物车,则会通知选项卡B和C,以便我们可以更新页面上的某些信息,或者通知用户页面已过时,或者类似的情况 我所尝试的: 这非常适合我的需要,但在IE 11或Safari中不起作用 所以我试着在任何地方使用广播频道API。它在IE中起作用,但在Safari中不起作用(我相信广播频道尚未定义) 然后我尝试了,它使用广播频道(如果可用),否则使用Javascript 如何在Safari 10+;中使用BroadcastChannel API或类似工具;?,javascript,safari,local-storage,broadcast-channel,Javascript,Safari,Local Storage,Broadcast Channel,问题: 我需要一个客户端Javascript解决方案(jQuery很好),其中一个浏览器窗口/选项卡中的事件可以广播到同一域中的其他窗口/选项卡。例如,如果在选项卡a中更新购物车,则会通知选项卡B和C,以便我们可以更新页面上的某些信息,或者通知用户页面已过时,或者类似的情况 我所尝试的: 这非常适合我的需要,但在IE 11或Safari中不起作用 所以我试着在任何地方使用广播频道API。它在IE中起作用,但在Safari中不起作用(我相信广播频道尚未定义) 然后我尝试了,它使用广播频道(如果可用
localStorage
伪造它。他们的演示页面在Safari中运行良好,但在我的网站上,我发现它在Safari 9中运行良好,而不是在10-12中(使用BrowserStack和一台运行Safari 12的真正Mac进行测试)。在调试他们的脚本时,当另一个选项卡中的localStorage
发生更改时,应该触发的脚本似乎不会触发。但这实际上只是一个问题当您有document.domain
集时,我会这样做
我相信这是一样的。但是,尽管Chrome在2012-2017年就出现了这个问题,但Safari显然是在2017年左右推出的
我在Safari中没有发现其他人讨论这个bug,但我可以很容易地证明这一点。打开使用相同document.domain
值的两个选项卡并运行以下脚本:
表A:
$(window).on("storage", function (e) {
alert('storage was modified');
});
表B:
localStorage.setItem("test", "123");
在Safari 9中,选项卡A将弹出警报。在Safari 10+中,它不会
如果我删除document.domain
,它就会工作。请注意,我们在这些页面上使用的是document.domain
,但在本例中,它们实际上位于同一个域中。但是,整个站点的其他场景需要document.domain
,因此我无法删除它
我也试着看了看。它有一个事件系统,但它似乎只在同一个选项卡中工作(在任何浏览器中)。除非我遗漏了什么
那么,当您设置了document.domain
时,是否有BroadcastChannel polyfill或类似的库在Safari 10+中真正起作用?或其他方法
注:
- 我知道BroadcastChannel和
的“storage”事件只对当前选项卡以外的选项卡触发。这不是我的问题,事实上是我想要的localStorage
- 我还看到过一些帖子,这些帖子让我相信,在Safari中,依靠
的替代解决方案可能无法在私人浏览模式下工作。编辑:看起来这确实有效,但在我的测试中,它没有与任何其他选项卡共享本地存储,甚至没有与同一窗口中的其他私有选项卡共享本地存储。所以这帮不了什么忙。理想情况下,一个解决方案也能解释这一点,但在这一点上,我对Safari 10+中对我有用的任何东西都很满意。我确实在store.js项目中看到过一个例子,他们说他们在这种情况下是这样做的,所以这听起来至少是可能的localStorage
- 我试着用
来考虑其他方法,它每隔几秒钟检查setInterval
是否有更新。即使从理论上讲,这似乎真的很粗糙和不可靠(你怎么知道什么时候所有的页面都“收到”了更新,这样你就可以清除它?)。你怎么知道什么时候用这种黑客方式而不是使用localStorage
的首选方法?Safari 10+将报告它支持localStorage
,因此您无法真正检测到它,对吗?它“支持”它,只是不能正常工作localStorage
document.domain
。我认为它在本例中使用了indexDB,这似乎是完全的矫枉过正,但我似乎没有选择
在较新版本的Safari中,它也适用于Safari专用窗口。我已经在我的所有脚本中尝试了在私有模式下捕获Safari的旧版本,否则它会抛出错误
如果不是Safari,我会使用默认情况下使用
BroadcastChannel
,对于IE 11这样的情况,我会使用localStorage
。注意,只有在Safari中通信的窗口处于顶级时才有效,但如果一个窗口是iframe,则不起作用。由于Safari不支持本机广播频道,因此它只能使用本地存储。当在iframe中使用localStorage时,它不仅绑定到当前域的上下文,而且“双键”绑定到该域+window.top域。在需要时恢复到本地存储,因此无需使用其他library@NicholasHaley我相信我在尽可能地使用浏览器本地广播频道。我这样做的方式是,在两个插件之间,它基本上首先使用本机广播频道,然后返回到基于本地存储的解决方案,然后返回到基于indexDB的解决方案。@Roobot我有一个项目,我需要做类似的事情。在大多数情况下,“广播频道”库能够在本机广播频道支持不可用的情况下找到回退(localStorage或IndexedDB)。如果您的项目中需要更多的控制(如我所做的),那么第二个参数将获取一个对象,您可以在其中指定类型。需要说明的是,github.com/pubkey/broadcast-channe将尽可能使用本机广播频道。可能会简化您的代码。看:@NicholasHaley哦,真有趣!我想我从没见过医生的那部分。我看到它说“这个行为类似于BroadcastChannel API”