首页 > 解决方案 > 如何在 Safari 10+ 中使用 BroadcastChannel API 或类似的东西?

问题描述

问题:

我需要一个客户端 Javascript 解决方案(jQuery 很好),其中一个浏览器窗口/选项卡中的事件可以广播到同一域上的其他窗口/选项卡。例如,如果在选项卡 A 中更新了购物车,则选项卡 B 和 C 会收到通知,以便我们可以更新页面上的一些信息,或者通知用户该页面已过时,或类似的事情。

我试过的:

BroadcastChannel API非常适合我的需求,但在 IE 11 或 Safari 中不起作用。

所以我尝试了这个 polyfill,这样我就可以在任何地方使用 BroadcastChannel API。它在 IE 中有效,但在 Safari 中无效(我相信 BroadcastChannel 仍未定义)。

然后我尝试了 sysend.js,它使用 BroadCastChannel(如果可用),否则使用localStorage. 他们的演示页面在 Safari 中运行良好,但在我的网站上,我发现它在 Safari 9 中运行,但不是 10-12(使用 BrowserStack 和一台运行 Safari 12 的真实 Mac 进行测试)。调试他们的脚本,似乎在不同选项卡中更改时应该触发的存储事件localStorage根本不会触发。但这实际上只是当您document.domain设置时才会出现的问题,我这样做了。

我相信这与这个旧的 Chrome 错误相同。但是,虽然 Chrome 在 2012 年至 2017 年出现了这个问题,但 Safari 显然是在 2017 年左右推出的?

我还没有发现其他人在 Safari 中讨论这个错误,但我可以很容易地证明这一点。打开两个使用相同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,整个站点的其他场景都需要它,因此我无法将其删除。

我还尝试查看store.js。它有一个事件系统,但它似乎只能在同一个选项卡中工作(在任何浏览器中)。除非我错过了什么。

document.domain那么,当你有一个集合时,是否有任何 BroadcastChannel polyfill 或类似的库可以在 Safari 10+ 中实际运行? 或任何其他方式来做到这一点?

笔记:

标签: javascriptsafarilocal-storagebroadcast-channel

解决方案


我找到了一种解决方法,但我会留下这个问题,因为我仍然希望看到更好的答案。

作为最后的手段,我最终在两种不同的消息执行方式之间切换,具体取决于浏览器。

基本上,如果是 Safari,我使用https://github.com/pubkey/broadcast-channel (您可以从https://github.com/pubkey/broadcast-channel/blob/master/dist/获得缩小的香草 JS 版本lib/browser.min.js)。即使您有一套,这似乎也适用于所有版本document.domain。我认为它在这种情况下使用 indexDB,这似乎完全是矫枉过正,但我​​似乎别无选择。

它也适用于较新版本的 Safari 中的 Safari 私人窗口。我已经在我的所有脚本中为旧版本的 Safari 在私有模式下尝试了捕获,否则它会抛出错误。

如果不是 Safari,我会使用sysend.js,它BroadcastChannel默认使用并回退到localStorageIE 11 等情况。


推荐阅读