Как я могу использовать 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.

Другие вопросы по тегам