Создание асинхронного сайта неразрывно связано с постоянным взаимодействием фронтенда и бэкенда сайта. При этом возникает задача синхронизации действий на различных вкладках сайта. Если вы выполняете опрос бэкенда о наступлении новых событий, то отсутствие синхронизации приведет к тому, что на сервер будет идти больше запросов, чем могло бы быть. Я делал десктопные нотификации из браузера, и отсутствие синхронизации приводило к тому, что человек видел двойные нотификации. Реализация синхронизации на уровне бэкенда, в общем случае, достаточна проблематична и сложна.

Для синхронизации действий на разных страницах одного сайта необходимо иметь возможность передать информацию от любой страницы к любой. Потенциально есть несколько способов создать синхронизации даннных между вкладками:

  • Общие воркеры. Хороший и скорее всего оптимальный способ для страниц, которые могут быть открыты часами
  • localStorage. LocalStorage мгновенно синхронизируется между вкладками. Крайне простой интерфейч

Для своей библиотеки я выбрал localStorage, потому что решил, что с ним смогу быстрее сделать решение.

Алгоритм синхронизации достаточно прост:

  1. Для каждого вызываемого действия, текущая страница проверяет, кто делал это действие в прошлый вызов
  2. Если текущая страница делала действие до этого, то страница выполняет действие
  3. Если в прошлый раз действие делалось на другой странице, то запрашивается жива ли другая страница
  4. Если другая страница жива, то ничего не делается или делается пассивное действие
  5. Если другая страница не отвечает (закрыта или зависла), то текущая страница осуществляет действие

Реализация этого алгоритма в чистом виде будет ограничена скоростью ответа сервера и частотой запросов: если сервер опрашивается чаще, чем осуществляется скорость ответа от сервера на запрос, то запросы будут идти со всех открытых страниц.

Более правильным является введение отдельной проверки на то жива ли страница:

  1. Для каждого вызываемого действие в localStorage заносится запись, что такое действие выполнила такая то страница и эта страница помечается активной
  2. Запускается бесконечный цикл, которая для каждого действия раз в секунду подтверждает, что страница, выполнившая действие жива
  3. При попытки выполнения действия на другой странице, проверяется есть ли активная страница и, если есть, то жива ли она
  4. Если активная страница есть и жива, то действие не выполняется или делается пассивное действие
  5. Если нет активной страницы или активная страница давно не подтверждала, что она жива, то выполняется действие и новая страница помечается активной

Такой алгоритм дает основу для синхронизации действий между вкладками. Именно его я реализовал в библиотеке для синхронизации действий. В качестве примера приводится работа с видео плеером: запуск видео на одной странице остановит видео на всех остальных страницах.

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