Шина событий (EventBus) в JavaScipt
Доброго времени суток! Сегодня мы рассмотрим с Вами, что такое шина событий и как использовать ее в JavaScript.
Шина событий обычно используется в качестве механизма связи между несколькими компонентами, т.е. EvenBus это что-то вроде центру управления событиями. Один компонент отправляет (публикует) сообщения, а другие компоненты подписываются на них, и, при получении, обрабатывают. Таким образом обеспечивается асинхронный процесс связи между компонентами, или между плагинами и ядром системы, если в системе реализована возможность добавления сторонних плагинов.
Шина событий, по сути, использует шаблон проектирования "Pub-Sub" (издатель-подписчик). Например, несколько компонентов A, B и C подписываются на событие some.event, а затем определенный компонент D публикует это событие в шине событий, шина событий уведомит всех подписанные компоненты A, B, C о событии, при необходимости передав подписчиками какие-либо данные, отправленные из компонента D.
Итак, вот сам код.
HTML-файл
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Bus (шина событий)</title>
<style>
html, body {
margin: 0;
padding: 0;
min-height: 100%;
}
#app {
padding: 5px;
background: #f0f0f0;
min-height: 100%;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
gap: 10px;
}
.column {
background: #fff;
border: 1px solid #ddd;
display: flex;
flex-direction: column;
flex-basis: 100%;
flex: 1;
padding: 5px;
}
.block {
min-height: 100px;
}
.block_a {
}
.block_b {
}
#messageLog {
margin-top: 5px;
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<div class="row">
<div class="column block block_a">
<button id="button1">Button 1</button>
</div>
<div class="column block block_b">
<button id="button2">Button 2</button>
</div>
</div>
<div class="row">
<div class="column" id="messageLog">
This is log message
</div>
</div>
</div>
<script src="src/main.js" type="module"></script>
</body>
</html>
файл main.js
import EventBus from "./EventBus.js";
/**
*
* @param {*} id
* @returns
*/
const element = id => document.querySelector(id);
// события в отдельном объекте, чтобы не повторять строчки
const EventType = {
Counter: {
Increment: "counter.increment", // увеличить счетчик
Decrement: "counter.decrement" // уменьшить счетчик
}
}
function main()
{
const btn1 = element('#button1');
const btn2 = element('#button2');
const messageLog = element('#messageLog');
const eventBus = new EventBus();
// Подписываемся на событие
eventBus.subscribe(EventType.Counter.Increment, (counter) => {
messageLog.innerText = "Счетчик: " + counter;
});
eventBus.subscribe(EventType.Counter.Decrement, (counter) => {
messageLog.innerText = "Счетчик: " + counter;
});
let counter = 0;
// при нажатии клавиш отправляем (публикуем) событие с данными в шину
btn1.addEventListener('click', () => eventBus.publish(EventType.Counter.Increment, ++counter));
btn2.addEventListener('click', () => eventBus.publish(EventType.Counter.Decrement, --counter));
}
document.addEventListener('DOMContentLoaded', main);
Файл EventBus.js
class EventBus
{
constructor()
{
// создаем объект, который будет хранить события событий
this.eventObject = {};
// идентификатор
this.callbackId = 0;
}
// публикуем событие
publish(eventName, ...args)
{
// получаем все обработчики прикрепленные к данному событию
const callback = this.eventObject[eventName];
if (!callback) return console.warn(eventName + ": событие не найдено!");
// выполняем каждый обработчик
for (let id in callback) {
// передаем параметры обработчику
callback[id](...args);
}
}
// Подписка на событие
subscribe(eventName, callback)
{
// инициализируем событие, если оно еще не создано
if (!this.eventObject[eventName]) {
this.eventObject[eventName] = {};
}
// получаем идентификатор
const id = this.callbackId++;
// сохраняем обработчик события подписчика в формате: [имя_события][идентификатор]
// идентификатор получен выше
this.eventObject[eventName][id] = callback;
// Каждый раз, когда вы подписываетесь на событие, генерируется уникальная функция отмены подписки
const unsubscribe = () => {
// удаляем обработчик
delete this.eventObject[eventName][id];
// Если у этого события нет подписчиков, удаляем вообще все событие
if (Object.keys(this.eventObject[eventName]).length === 0) {
delete this.eventObject[eventName];
}
};
return { unsubscribe };
}
}
export default EventBus;
-
- Михаил Русаков
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.