Подписка на событие
Разбираю сайт Читай-город (скачал веб-страницу полностью). Среди файлов нашел Читай-город - интернет-магазин книг_files\eventEmitter.js.Без названия, в котором прописывается работа с событиями
function EventEmitter(){
var eventSubscribers = {};
//Диспетчирезация события
this.dispatch = function (eventName, payload){
if(eventSubscribers.hasOwnProperty(eventName)){
eventSubscribers[eventName].forEach(function (eventHandler){
eventHandler(payload);
});
}
return true;
};
//Подписка на событие. Возвращает метод отписки handler от события
this.subscribe = function (eventName, handler){
if(typeof handler !== 'function'){
return;
}
if(!eventSubscribers.hasOwnProperty(eventName)){
eventSubscribers[eventName] = [];
}
eventSubscribers[eventName].push(handler);
return function (){
eventSubscribers[eventName] = eventSubscribers[eventName].filter(function (currentHandler) {
return currentHandler !== handler;
});
}
}
}
window.eventEmitter = new EventEmitter();
Судя по коду
eventSubscribers[eventName].push(handler);
сначала в массив, соответствующий элементу-событию eventName, добавляется функция-обработчик handler, а затем
return function (){
eventSubscribers[eventName] = eventSubscribers[eventName].filter(function (currentHandler) {
return currentHandler !== handler;
});
}
все функции-обработчики, не совпадающие с функцией текущего вызова handler, записываются в массив eventSubscribers[eventName] и этот результат возвращается из функции subscribe. Тогда
- зачем мы добавляли обработчик
handlerв массив и - и что должна делать функция
subscribe?
P.S. Этот вопрос схож с Диспетчеризация событий в eventEmitter, но это не тот же вопрос, так как там обсуждалась диспетчеризация, а здесь подписка на события.
Этот вопрос был задан, так как в других файлах, например, Читай-город - интернет-магазин книг_files\auth.js(1).Без названия, функция eventEmitter.subscribe использовалась для подписки на событие функции-обработчика, а не для отписки.
eventEmitter.subscribe(popupGreeting.events.closePopup, function () {
window.location.reload();
});
Зачем вообще нужна отписка для функции-обработчика?
Ответы (1 шт):
- Мы хотели подписать обработчик на событие.
- Эта функция подписывает обработчик на событие и возвращает возможность отписать обработчик от события.
Массив не обязательно должен перезаписываться, можно было например удалить из него одну функцию методом .splice( functionIndex, 1 ).
Я в прошлом ответе (Диспетчеризация событий в eventEmitter) уже писал, что возвращаемая функция служит для отписки от события. Заметьте, что там возвращается функция, а не сразу код, отписывающий функцию. Это две разных задачи, и вторая задача отписки не обязательна. Вы её можете не вызывать если не нужно, и отписка не будет происходить. Но возможность отписки обязательна в таких системах событий. Тут она реализована как возвращаемая функция. В других библиотеках реализуется как отдельный метод, например .unsubscribe() или .off().
Вот пример подписки и отписки:
// .............. тут подписка происходит ▼
let unsubscribe = eventEmitter.subscribe(popupGreeting.events.closePopup, function () {
window.location.reload();
});
//... какие-то задачи и время проходит ...
// а тут отписка ▼
unsubscribe();
Метод .subscribe() делает всегда только одно - подписку. Но при этом даёт возможность потом отписаться. Не заставляет и не делает это, а только возвращает такую возможность. Вы можете вообще удалить эту отписку если хотите. Там она просто написана для ситуации, когда это необходимо. А отписывать события бывает необходимо. Приведу пример с DOM. Допустим, показался попап, при этом он на window повесил обработку изменения размеров окна, чтобы делать какие-то корректировки у себя. Когда попап закрылся, то обработку размеров окна нужно снять. Если не снять, то их скопится много, при очередном показе попапов, а в памяти все попапы буду храниться, потому что сборщик мусора видит, что на них ещё остались ссылки из обработчиков.