Шина событий (EventBus) в JavaScipt

Шина событий (EventBus) в JavaScipt

Шина событий (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;




Источник

НЕТ КОММЕНТАРИЕВ

Оставить комментарий