Как я могу использовать BroadcastChannel API или что-то подобное в Safari 10+?
Проблема:
Мне нужно решение Javascript на стороне клиента (с jQuery все в порядке), когда событие в одном окне / вкладке браузера может передаваться другим окнам / вкладкам в том же домене. Например, если корзина обновляется на вкладке A, вкладки B и C получают уведомление, чтобы мы могли обновить некоторую информацию на странице или уведомить пользователя о том, что страница устарела или что-то в этом роде.
Что я пробовал:
BroadcastChannel API идеально подходит для моих нужд, но не работает в IE 11 или Safari.
Итак, я попробовал этот polyfill, чтобы я мог использовать API BroadcastChannel везде. Это работало в IE, но не в Safari (я думаю, что BroadcastChannel остался неопределенным).
Затем я попытался sysend.js, который использует BroadCastChannel, если он доступен, в противном случае подделывает его с помощью localStorage
, Их демонстрационная страница прекрасно работает в Safari, но на моем сайте я обнаружил, что она работает в Safari 9, но не 10-12 (протестировано с использованием BrowserStack и одного реального Mac с Safari 12). Отладка их скрипта, кажется, событие хранилища, которое должно сработать, когда 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. У него есть система событий, но она работает только в одной вкладке (в любом браузере). Если я что-то упустил.
Итак, есть ли какая-нибудь библиотека или аналогичная библиотека BroadcastChannel, которая на самом деле работает в Safari 10+, когда у вас есть document.domain
установлен? Или любой другой способ сделать это?
Примечания:
- Я знаю, что BroadcastChannel и событие "хранилища" для
localStorage
Огонь только для вкладок, кроме текущей. Это не моя проблема, и на самом деле это желательно для меня. - Я также видел сообщения, которые заставляют меня поверить, что альтернативное решение опирается на
localStorage
скорее всего не будет работать в режиме приватного просмотра в Safari. РЕДАКТИРОВАТЬ: кажется, это было исправлено в Safari 11, поэтому он работает, но в моих тестах он не делил localStorage ни с какими другими вкладками, даже с другими вкладками Private в том же окне. Так что это не сильно поможет. В идеале, решение также должно учитывать это, но на данный момент я был бы рад всему, что сработало в Safari 10+ для меня. Я видел пример в проекте store.js, где они сказали, что сделали это так, что в этом случае он будет использовать cookie-файлы, так что это звучит по крайней мере возможно. - Я пытался думать о других способах сделать это с
setInterval
который проверяетlocalStorage
для обновления каждые несколько секунд или что-то. Даже в теории это кажется действительно хакерским и ненадежным (как бы вы узнали, когда все страницы "получили" обновление, чтобы вы могли его очистить?). И как вы узнаете, когда делать это таким хакерским способом вместо одного из предпочтительных методов, использующихlocalStorage
? Safari 10+ сообщит, что поддерживаетlocalStorage
так что вы не можете обнаружить его, не так ли? Он "поддерживает" его, он просто не работает правильно.
0 ответов
Я нашел обходной путь, но оставлю этот вопрос открытым, потому что мне все равно хотелось бы получить лучший ответ.
В крайнем случае, мне пришлось переключаться между двумя разными способами обмена сообщениями в зависимости от браузера.
В принципе, если это Safari, я использую https://github.com/pubkey/broadcast-channel (вы можете получить уменьшенную версию vanilla JS с https://github.com/pubkey/broadcast-channel/blob/master/dist/lib/browser.min.js). Кажется, это работает во всех версиях, даже если у вас естьdocument.domain
установлен. Я думаю, что в этом случае он использует indexDB, что кажется полным излишеством, но у меня, похоже, нет выбора.
Он также работает в частных окнах Safari в более новых версиях Safari. Я пробовал использовать уловки во всех моих скриптах для более старых версий Safari в частном режиме, где в противном случае возникли бы ошибки.
Если это не Safari, я использую sysend.js, который используетBroadcastChannel
по умолчанию и возвращается к localStorage
для таких случаев, как IE 11.