4 Способа обмена данными между вкладками браузера в режиме реального времени



Книга 4 Способа обмена данными между вкладками браузера в режиме реального времени

На протяжении многих лет возможности браузеров постоянно увеличивались в ответ на растущие потребности веб-приложений. И теперь у нас есть множество способов получения одной и той же (или схожей) функциональности. На такую особенность браузеров, как возможность обмена данными между вкладками, редко обращают внимание. Рассмотрим несколько сценариев, в которых она может потребоваться:


  • Изменение темы (например, тёмная или светлая тема) приложения распространяется на уже открытые вкладки браузера.
  • Получение последнего токена для аутентификации и использование его во всех вкладках браузера.
  • Синхронизация состояния приложения во всех вкладках браузера.

На момент написания этой статьи существовало несколько достойных внимания подходов, в соответствии с которыми осуществляется обмен данными между вкладками браузеров. У каждого из этих подходов свои сильные и слабые стороны, поэтому остановимся на них подробнее, чтобы вы могли найти подходящий для вас вариант.


1. «Events» («События») в локальном хранилище данных


Возможно, вы уже использовали LocalStorage, который доступен на разных вкладках в рамках одного и того же приложения-источника. Но знаете ли вы, что LocalStorage поддерживает события? Эту функцию можно использовать для обмена данными между вкладками браузера: хранилище обновляется, после чего событие получат другие вкладки.


Например, в одной вкладке выполняется следующий код JavaScript:


window.localStorage.setItem("loggedIn", "true");

И другие, прослушивающие событие вкладки получат это событие:


window.addEventListener('storage', (event) => {
if (event.storageArea != localStorage) return;
if (event.key === 'loggedIn') {
// Делаем что-нибудь с «event.newValue»
}
});

Но здесь есть несколько ограничений:


  • Событие не срабатывает для вкладки, на которой выполняется действие по вводу значений в хранилище.
  • Этот подход имеет негативные последствия для большого объёма данных: из-за синхронности выполняемых в LocalStorage действий основной поток пользовательского интерфейса может быть заблокирован.

Более подробная информация содержится в разделе «Storage Events» документации MDN.


2. API широковещательного канала


API широковещательного канала позволяет осуществлять обмен данными между вкладками, окнами, фреймами, Iframes и веб-воркерами. Одна вкладка создаёт что-то и опубликовывает это на канале:


const channel = new BroadcastChannel('app-data');
channel.postMessage(data);


А другие вкладки прослушивают канал:


const channel = new BroadcastChannel('app-data');

channel.addEventListener ('message', (event) => {
console.log(event.data);
});

const channel = new BroadcastChannel('app-data');

И таким образом происходит обмен данными между контекстами браузера (окнами, вкладками, фреймами или Iframes). Такой способ обмена данными между вкладками браузера очень удобен. Тем не менее safari и IE его не поддерживают. Более подробная информация содержится в разделе «BroadcastChannel» документации MDN.


Подсказка: выкладывайте на Bit (Github) переиспользуемые компоненты для своих проектов. Здесь очень просто размещать, документировать и организовывать независимые компоненты из любого проекта.


Задействуйте этот ресурс для максимально многократного использования кода и совместной работы над независимыми компонентами, а также для создания масштабируемых приложений.


Bit поддерживает Node, TypeScript, React, Vue, Angular и много других инструментов.


Пример: просмотр повторно используемых компонентов React, выложенных на Bit.dev

3. Сервис-воркеры для отправки сообщений


Здесь у вас может возникнуть вопрос: «Откуда взялись тут сервис-воркеры?». Вообще-то они тоже поддерживают отправку сообщений, поэтому сервис-воркеры можно использовать для обмена данными между вкладками браузера.


Вот как отправляется сообщение с помощью сервис-воркеров:


navigator.serviceWorker.controller.postMessage({
broadcast: data
});

А принимающий воркер на другой вкладке браузера прослушивает это событие:


addEventListener('message', async (event) => {
if ('boadcast' in event.data ) {
const allClients = await clients.matchAll();
for (const client of allClients) {
client.postMessage(event.broadcast);
}
}
});

Это надежный способ передачи сообщений, предоставляющий больше контроля. Но для внедрения сервис-воркеров требуются дополнительные знания об API Service Worker и чуть больше работы. Так что, если другие подходы не работают, стоит обратить внимание на этот. Более подробная информация содержится в разделе «Service Worker API» документации MDN, а весь пример доступен по этой ссылке.


4. Отправка сообщений между окнами


Подход Window.postMessage()  —  один из традиционных способов обмена данными между вкладками браузера. Сообщение отправляется так:


targetWindow.postMessage(message, targetOrigin)

А целевое окно прослушивает события:


 рwindow.addEventListener("message", (event) => {
if (event.origin !== "http://localhost:8080")
return;
// Делаем что-нибудь
}, false);

Одно из преимуществ этого подхода перед другими  —  возможность поддержки обмена данными между разными источниками. Но есть и ограничение: необходима ссылка на другую вкладку браузера. Поэтому этот подход только для вкладок браузера, открытых через window.open() или document.open(). Более подробная информация содержится в документации MDN.


Заключение


Надеюсь, статья была для познавательной и рассмотренные в ней подходы будут полезны для ваших веб-приложений. Каждый подход уникален и имеет свои варианты использования.


Кроме этих четырёх подходов, для обмена данными между вкладками браузера и даже между устройствами в режиме реального времени применяются Websockets («веб-сокеты») и Server-Sent Events («события, посылаемые сервером»). Но для этого понадобится веб-сервер. А вот рассмотренные в статье подходы не зависят от веб-сервера, и их применение позволяет осуществлять обмен данными в браузере без него и делать это быстро.


Спасибо за внимание!


А теперь приступайте к работе над собственным кодом!!! ❤️️


490   0  

Comments

    Ничего не найдено.