Шаблоны развязки: очередь событий

Мощный шаблон проектирования для системного проектирования

Вы можете загрузить полный код здесь, чтобы продолжить.

Сегодня мы поговорим об очень интересном паттерне, используемом в системном дизайне. Будь то финансовая серверная служба, приложение реального времени или видеоигра, этот шаблон делает систему удобной в обслуживании и простой в масштабировании.

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

В двух словах о развязке

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

Цель

Когда мы создаем сложные системы, требующие масштабирования, мы редко будем работать в одиночку. Это означает, что разные люди должны будут читать и изменять разные части проекта одновременно.

Это может вызвать много разочарований, если что-то сделано неправильно.

Например, предположим, что мы создаем социальную сеть. Каждому человеку в вашей команде назначен отдельный компонент. Один отвечает за работу в сети, другой за функции чата, а третий за загрузку каналов и изображений.

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

Хотя это может быть правдой, сеть и чат выполняют совершенно разные функции, которые не полностью связаны друг с другом. Но в то же время чату нужны данные, которые сетевой компонент получает и обрабатывает.

Избегайте кода спагетти

Если бы мы реализовали наивный способ, у нас бы чат зависел от сетевого компонента, и наоборот.

Любое изменение, сделанное в сетевом компоненте, может повлиять на функциональность чата, и ему, возможно, потребуется вторгнуться в код сетевого пользователя, чтобы его код снова заработал. Здесь все может стать очень запутанным. Парню в чате не нужно изменять код, не относящийся к его сфере деятельности. Или, по крайней мере, минимально возможную сумму.

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

Очередь событий спешит на помощь

Очередь событий похожа на центральную станцию, посредника, куда приходят все «пакеты» и распределяются по соответствующим адресатам. Этот шаблон разделяет все коммуникации с помощью системы, основанной на событиях.

Представьте, что вы смотрите YouTube, вам действительно понравился канал пользователя X и вы хотите получать уведомления, когда они загружают новое видео. Каждый раз, когда X загружает новое видео, вы, который теперь являетесь подписчиком, получите электронное письмо (событие).

Очередь событий работает точно так же. Компонент отправляет событие в очередь, а очередь обрабатывает и рассылает все эти сообщения любому компоненту, подписанному на это событие.

Строительные блоки EventQueue

Мероприятие

Событие - это структура, которая определяет, какими будут отправленные и полученные данные (их тип), и отслеживает, кто их слушает.

Отправитель

Отправитель похож на ютубера, он отправляет сообщение в очередь событий, и это все, о чем ему нужно беспокоиться. Отлично!

Слушатель

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

Функция обработчика

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

Очередь событий

Очередь событий будет получать сообщения о событиях от отправителей и транслировать их соответствующим подписчикам.

Реализация очереди событий

Теперь, когда мы более знакомы с тем, как это работает, давайте реализуем его на JavaScript.

Начнем с реализации класса eventQueue

Здесь мы видим пару вещей.

Очередь

  • Очередь будет использоваться для приема и рассылки сообщений о событиях.

Слушатели сообщений

  • Список всех компонентов, которые прослушивают событие типаMessage

Бег

  • Состояние нашей EventQueue, мы можем остановить цикл, сделав его = false;

Начинать()

  • Запускает цикл

runLoop ()

  • Он выгружает следующее событие в очереди и рассылает свое сообщение всем зарегистрированным слушателям. (подписчики)
  • Это одна из самых важных частей. Циклы событий асинхронно ожидают сообщений, отправленных в свою очередь.
  • Причина, по которой нам нужно сделать это асинхронной функцией, заключается в том, что JavaScript является однопоточным, поэтому, если мы этого не сделаем, цикл заблокирует все остальное в нашем коде, и мы не сможем получить какой-либо ввод или даже остановить цикл. .

Создание события

Мы можем создавать различные типы событий, такие как «клиент подключен», «клиент отключен», «клиент присоединился к группе», «клиент покинул группу» и т. Д.

Чтобы создать событие, все, что нам нужно сохранить, - это прослушиватели и фактическое отправляемое сообщение (полезная нагрузка).

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

Примечание. В этом случае каждый слушатель должен будет реализовать метод под названием HandleMessage, но вы можете выбрать имя метода.

Метод может делать с информацией все, что угодно.

Регистрация события

Внутри класса EventQueue нам нужно добавить метод для регистрации компонента, чтобы он мог прослушивать событие нашего сообщения.

Нам нужно будет добавить массив Listeners для каждого уникального события и создать функцию регистрации для добавления компонентов к этому событию.

В этом случае мы уже создали messageListeners [] при создании класса EventQueue , поэтому мы можем добавить метод регистрации. Все зарегистрированные компоненты будут получать уведомления всякий раз, когда событие этого типа запускается.

Собираем все вместе

Что происходит?

Компоненты A и B будут только прослушивать и обрабатывать полученное сообщение, поэтому им не нужен доступ к экземпляру eventQueue.

Компонент C будет отправлять сообщения, поэтому ему нужен доступ к методам eventQueue.

Затем мы регистрируем компоненты A и B для получения событий типа Message.

Мы отправляем два сообщения от Компонента C, и они транслируются в зарегистрированные компоненты. (А и В)

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

Обратите внимание, что этот код создаст бесконечный цикл, поскольку мы хотим запускать наш eventQ во время работы нашего приложения. Вы можете добавить eventQ.running = false в конец файла main.js, но только первое сообщение будет зарегистрировано, поскольку мы останавливаем цикл.

Результат будет выглядеть так.

Отправляются два события сообщения, и, поскольку этот тип события имеет два слушателя, он печатается дважды, по одному каждым слушателем,

Заключение

Очередь событий - это очень мощный шаблон проектирования развязки. Это делает внутреннюю коммуникацию системы намного более эффективной и позволяет упорядочивать действия во времени.

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

В JavaScript мы используем async, чтобы запускать его «одновременно», но мы могли бы сделать это более эффективно в многопоточных языках, таких как GO.

Это все на сегодня.

Удачного кодирования!

Примечание из JavaScript In Plain English

Мы всегда заинтересованы в продвижении качественного контента. Если у вас есть статья, которую вы хотели бы отправить в JavaScript In Plain English, отправьте нам электронное письмо по адресу [email protected] с вашим именем пользователя Medium, и мы добавим вас в качестве автора.

Также мы выпустили три новых издания! Проявите любовь к нашим новым публикациям, подписавшись на них: AI на простом английском, UX на простом английском, Python на простом английском - спасибо и продолжайте учиться!