0

Разбираю сайт Читай-город (скачал веб-страницу полностью). Среди файлов нашел Читай-город - интернет-магазин книг_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. Тогда

  1. зачем мы добавляли обработчик handler в массив и
  2. и что должна делать функция subscribe?

P.S. Этот вопрос схож с Диспетчеризация событий в eventEmitter, но это не тот же вопрос, так как там обсуждалась диспетчеризация, а здесь подписка на события.

Этот вопрос был задан, так как в других файлах, например, Читай-город - интернет-магазин книг_files\auth.js(1).Без названия, функция eventEmitter.subscribe использовалась для подписки на событие функции-обработчика, а не для отписки.

eventEmitter.subscribe(popupGreeting.events.closePopup, function () {
                window.location.reload();
            });

Зачем вообще нужна отписка для функции-обработчика?

  • stackoverflow - не форум. Не редактируйте интенсивно полотно вопроса находу, потому что тогда ответы обесцениваются. И принимайте ответ, если он верен по вашему мнению или помог. Последний вопрос вы можете найти в гугле или задать отдельно. Так ваш вклад будет ценным для всех, а не только решит вашу проблему. –  Oct 24 '20 at 10:28
  • @PavelGrishaev Вы очень хорошо ответили на вопрос https://ru.stackoverflow.com/questions/1194442/%d0%a1%d0%b5%d0%bc%d0%b0%d0%bd%d1%82%d0%b8%d0%ba%d0%b0-%d1%81%d0%b2%d0%be%d0%b9%d1%81%d1%82%d0%b2%d0%b0-this-pop, но с последним вопросом я что-то застопорил и поэтому очень нужна ваша помощь. Ответьте на мой последний комментарий после вопроса. Вещь ведь действительно не стандартная - производится отписка, а не подписка. – ProgrammerOfParadoxThings Oct 24 '20 at 10:40
  • ответил в ответе –  Oct 24 '20 at 10:59

1 Answers1

0
  1. Мы хотели подписать обработчик на событие.
  2. Эта функция подписывает обработчик на событие и возвращает возможность отписать обработчик от события.

Массив не обязательно должен перезаписываться, можно было например удалить из него одну функцию методом .splice( functionIndex, 1 ).

Я в прошлом ответе (Диспетчеризация событий в eventEmitter) уже писал, что возвращаемая функция служит для отписки от события. Заметьте, что там возвращается функция, а не сразу код, отписывающий функцию. Это две разных задачи, и вторая задача отписки не обязательна. Вы её можете не вызывать если не нужно, и отписка не будет происходить. Но возможность отписки обязательна в таких системах событий. Тут она реализована как возвращаемая функция. В других библиотеках реализуется как отдельный метод, например .unsubscribe() или .off().

Вот пример подписки и отписки:

// .............. тут подписка происходит ▼
let unsubscribe = eventEmitter.subscribe(popupGreeting.events.closePopup, function () {
    window.location.reload();
});

//... какие-то задачи и время проходит ...

// а тут отписка ▼ unsubscribe();

Метод .subscribe() делает всегда только одно - подписку. Но при этом даёт возможность потом отписаться. Не заставляет и не делает это, а только возвращает такую возможность. Вы можете вообще удалить эту отписку если хотите. Там она просто написана для ситуации, когда это необходимо. А отписывать события бывает необходимо. Приведу пример с DOM. Допустим, показался попап, при этом он на window повесил обработку изменения размеров окна, чтобы делать какие-то корректировки у себя. Когда попап закрылся, то обработку размеров окна нужно снять. Если не снять, то их скопится много, при очередном показе попапов, а в памяти все попапы буду храниться, потому что сборщик мусора видит, что на них ещё остались ссылки из обработчиков.

  • скачайте веб-страницу Читай-город (если не затруднит конечно) и посмотрите в файл Читай-город - интернет-магазин книг_files\auth.js(1).Без названия Там со 160 по 214 строку используется функция eventEmitter.subscribe для подписки на события, а не для отписки. – ProgrammerOfParadoxThings Oct 24 '20 at 10:32
  • если внутри eventEmitter.subscribe происходит return function (){ eventSubscribers[eventName] = eventSubscribers[eventName].filter(function (currentHandler) { return currentHandler !== handler; }); }, то это означает, что будет точно выполнено, а не возможность исполнения (оператор return) @PavelGrishaev – ProgrammerOfParadoxThings Oct 24 '20 at 11:30
  • @ProgrammerOfParadoxThings , нет. Оператор return завершает исполнение текущего тела функции и возвращает результат. Но не делает вызов результата. Функция оттуда только возвращается, а не вызывается. Иначе не было бы никакого смысла писать там функцию и что-то возвращать, можно было бы просто исполнить код сразу. –  Oct 24 '20 at 12:21