Comments 15
Помимо вышеуказаных плюсов: легкость в тестировании. Из-за того, что модули связаны только событиями, для их тестирования достаточно тригеррить нужные события с нужными данными, без зависимостей от работы сторонних модулей
Фактически приходим к истокам. Событийная модель, как известно, используется во всех фреймворках для написания GUI desktop-приложений, будь то qt, wxWidgets, vcl… Теперь с усложнением веба и переходом от «веб-сайтов» до «веб-приложений» эта модель прекрасно себя чувствует и в разработке веб-фронтендов.
Но писать событийную модель на JQ — это еще то извращение. Это полностью искажает весь смыл и логику JQ — сначала находим объект, с которым будем работать, потом работаем с каждым из них. Я уже как 4 года пользуюсь своей поделкой, которая построена только на event-based модели, и скажу вам, что это небо и земля. Мыслить событиями гораздо удобнее, чем мыслить функциями. Да и повторное использование кода колоссальное.
Что-то я не помню, чтобы я что-то говорил о JQuery )))
Да лално… В защиту подхода автора: 4 года назад в jquery еще не было deferred'ов (да что там, jquery только-только появился тогда), они вообще только недавно появились, а вот эти вот объекты отложенного выполнения как раз хорошо решают проблему построения event-based модели.
Да лално… В защиту подхода автора: 4 года назад в jquery еще не было deferred'ов (да что там, jquery только-только появился тогда), они вообще только недавно появились, а вот эти вот объекты отложенного выполнения как раз хорошо решают проблему построения event-based модели.
Использую такую же модель, только не в файловом менеджере, а в похожей схеме. И вот мне интересно, возникла ли у вас проблема зацикливания событий и, если да, какой вариант её решения вы выбрали? Опишу на примере: есть блок с деревом папок и есть блок с иконками папок и файлов. Если открывать папку в одном из блоков, то тот генерирует событие «открыть папку», которое приходит во второй блок, а тот открывает папку в себе и, если нет специального условия, может сгенерировать такое же событие от себя — это и приведёт к «зацикливанию». У вас есть «специальное условие» (разделение обработчиков действий пользователей и реакции на события) или какая-то другая обработка?
У нас немного другая схема не так, как вы описали. Когда происходит клик по файлу (неважно где) вид поднимает событие клик, по которому ядро обращается к серверу. И собственно событие «open» им же и вызывается, когда получены корректные данные. Так, что ваш пример у нас просто невозможен.
Хотя в теории возможна ситуация зацикливания — в обработчике события вызываем другое событие, а в его обработчике снова первое событие. Наверно абсолютного способа избежать этого — нету. Это скорее вопрос конкретной реализации.
Наверно стоит отметить это, как еще один недостаток метода.
Хотя в теории возможна ситуация зацикливания — в обработчике события вызываем другое событие, а в его обработчике снова первое событие. Наверно абсолютного способа избежать этого — нету. Это скорее вопрос конкретной реализации.
Наверно стоит отметить это, как еще один недостаток метода.
По поводу разделения. Оно у нас есть, хотя и не в том смысле, как вы спрашиваете. Можно говорить о разных уровнях приложения где эта модель применяется. То, что я описал в примере можно считать «главным циклом» приложения — основная его логика и взаимодействие с пользователем. Кроме него есть еще «внутренние» слои приложения — например взаимодействие интерфейса (кнопки, контекстное меню) с командами. Что бы не «хардкодить» кнопки в самих командах, они у нас являются отдельными объектами и подписываются на событие «изменение» в командах.
Наверно в статье я допустил неточность — объектов, принимающих подписку может быть любое количество
Наверно в статье я допустил неточность — объектов, принимающих подписку может быть любое количество
Частично решить проблему генерации событий недоверенным кодом можно привязав observable объект к нашему объекту как «private» поле, выдав наружу интерфейс вида:
В нужном месте внутри объекта вызывается
Таким образом препятствуется возможность триггерить некоторые события извне.
Можно разрешить вызовы некоторых событий извне, опять же через интерфейс, который может дополнительно заведовать, что надо передать обязательно и что можно получить у вызывающей стороны
Конечно, это плодит некоторое количество писанины, которую можно и нужно оптимизировать.
var observable = new Observable();
this.onReady = function(callback){
observable.bind('ready', callback);
};
В нужном месте внутри объекта вызывается
observable.trigger('ready', {…});
Таким образом препятствуется возможность триггерить некоторые события извне.
Можно разрешить вызовы некоторых событий извне, опять же через интерфейс, который может дополнительно заведовать, что надо передать обязательно и что можно получить у вызывающей стороны
this.doSomething = function(var1, var2) {
observable.trigger('something', {var1: var1, var2: var2, urgentDefault: 'blabla'});
};
Конечно, это плодит некоторое количество писанины, которую можно и нужно оптимизировать.
Это возвращает нас к тому, с чего мы начали. При добавлении новых модулей придется добавлять новые проверки — усиливается связанность. Имхо, контроль данных в самих слушателях — более гибкое решение
Мы похоже друг друга не поняли. Какие именно модули и какие именно проверки? Все проверки идут прямо в модуле, в функциях, открытых наружу. Контроль данных в слушателях нарушает логику — слушателю должны быть переданы заведомо корректные данные. Или мы говорим о разных вещах?
В идеале, по описанной схеме, все триггеры будут выглядеть как obj.doSomething(); — либо вообще без параметров, либо с каким-то минимальным набором, который будет в этом самом методе проверен и отдан слушателям. Таким образом компонент сам внутри себя знает, что передать и как нормализовать данные. И ситуация obj.trigger('event', 'rubbish'); вообще не появится. Бинд при этом может быть какой угодно — obj.onSomething(function(var1, var2) { … }); как раз таки потому, что сам триггер спрятан.
В идеале, по описанной схеме, все триггеры будут выглядеть как obj.doSomething(); — либо вообще без параметров, либо с каким-то минимальным набором, который будет в этом самом методе проверен и отдан слушателям. Таким образом компонент сам внутри себя знает, что передать и как нормализовать данные. И ситуация obj.trigger('event', 'rubbish'); вообще не появится. Бинд при этом может быть какой угодно — obj.onSomething(function(var1, var2) { … }); как раз таки потому, что сам триггер спрятан.
На всякий случай уточню, что каждому модулю принадлежит ровно один observable-объект, который скрыт и с которым напрямую общается только модуль, все остальное взаимодействие идет с модулем через методы, которые он предоставляет.
Да, похоже мы друг друга не поняли:( Извиняюсь
Советую посмотреть на библиотеку js-signals, предназначенную как раз для работы с событиями (подпиской на них и вызова).
Sign up to leave a comment.
Применение Event-driven модели в веб-приложении