Event Bus є надзвичайно корисним інструментом, який дозволяє зробити компоненти у ваших застосунках незалежними один від одного. У використанні Event Bus є свої плюси та мінуси, які потрібно врахувати при реалізації, щоб надалі зберегти простий та зрозумілий код.
Але, без сумніву, Event Bus може значно пришвидшити реалізацію, а також спростити архітектуру ваших застосунків.
У цій статті, я хочу показати, як реалізувати простий Event Bus у JavaScript.
Що таке Event Bus?
Event Bus — реалізація популярного шаблону publisher/subscriber (видавець/підписник). Він може бути використаний для відокремлення окремих компонентів в рамках одного застосунку. Таким чином, будь-який компонент може реагувати на будь-яку подію без додаткового зв'язку з іншими компонентами. Необхідно просто бути підписаним на Event Bus.
Кожен subscriber може підписатись на конкретну подію. Після спрацювання цієї події, всі її підписники будуть сповіщені про це. У свою чергу publisher може публікувати події в Event Bus, чим запустить раніше створені підписки.
Реалізація Event Bus
У даній реалізації підписник є функцією. Зв'язок між подією та функціями, які до неї відносяться, реалізовано об'єктом EventCallbacksPair
:
function EventCallbacksPair( eventType, callback ) {
this.eventType = eventType;
this.callbacks = [ callback ];
}
Наш Event Bus буде містити список об'єктів EventCallbacksPair
(по одному на кожну подію).
Події можуть бути будь-якого типу. Зазвичай використовується string, але це не єдиний варіант.
Subscribe:
Кожен раз, коли підписник хоче підписатись на подію, може виникнути два наступних варіанти:
- Ніхто раніше ще не підписувався на цю подію, тому Event Bus не містить EventCallbacksPair для цього об'єкту.
- У даної події вже є підписники, тому Event Bus вже містить об'єкт EventCallbacksPair з потрібною подією.
У першому випадку нам потрібно створити новий об'єкт типу EventCallbacksPair і додати у список Event Bus. В другому випадку ми просто додаємо необхідну подію до вже наявного об'єкта в поле callbacks.
this.subscribe = function( eventType, callback ) {
const eventCallbacksPair = findEventCallbacksPair( eventType );
if(eventCallbacksPair)
eventCallbacksPair.callbacks.push( callback );
else
eventCallbacksPairs
.push( new EventCallbacksPair( eventType, callback ) );
}
Publish:
Коли в Event Bus публікується нова подія, можуть виникнути наступні варіанти:
- Event Bus містить EventCallbacksPair для цієї події.
- У нашому списку відсутні підписки на цю подію.
У першому випадку ми знаходимо EventCallbacksPair
і викликаємо всі функції зворотного виклику, які є в нього, в полі callbacks. В іншому випадку просто повідомляємо, що будь-які підписки на цю подію відсутні.
this.post = function( eventType ) {
const eventCallbacksPair = findEventCallbacksPair( eventType );
if( !eventCallbacksPair ) {
console.error("no subscribers for event " + eventType);
return;
}
eventCallbacksPair.callbacks.forEach( callback => callback() );
}
Фінальна реалізація:
Повна реалізація простого Event Bus. Також цей код можна знайти тут.
function EventBus() {
const eventCallbacksPairs = [];
this.subscribe = function( eventType, callback ) {
const eventCallbacksPair = findEventCallbacksPair(eventType);
if(eventCallbacksPair)
eventCallbacksPair.callbacks.push(callback);
else
eventCallbacksPairs.push( new EventCallbacksPair(eventType, callback) );
}
this.post = function( eventType, args ) {
const eventCallbacksPair = findEventCallbacksPair(eventType);
if(!eventCallbacksPair) {
console.error("no subscribers for event " +eventType);
return;
}
eventCallbacksPair.callbacks.forEach( callback => callback(args) );
}
function findEventCallbacksPair(eventType) {
return eventCallbacksPairs.find( eventObject => eventObject.eventType === eventType );
}
function EventCallbacksPair( eventType, callback ) {
this.eventType = eventType;
this.callbacks = [callback];
}
}
Ще немає коментарів