EDA – event driven architecture или событийно-ориентированная архитектура. Довольно известный подход к проектированию веб-приложений, который сильно облегчает разработку, когда связанные компоненты находятся на разных ветвях иерархии, делая их связь более прозрачной.
К слову о компонентах. Angular лишь недавно обзавелся своими настоящими компонентами, но реализация данного подхода была возможна и ранее, при помощи простых и вложенных директив.
Про EDA
Как нам говорит википедия, событие в EDA можно определить как «существенное изменение состояния». Известно, что компоненты в большинстве Фреймворков, находящиеся в прямом родстве, спокойно могут наследовать и передавать состояние, определяющее их поведение. Тем более с этим не возникает проблем у Angular, который реализует всеми нелюбимый two-way binding. Но все посылы команды разработчиков говорят о том, что это не хорошо и нужно привыкать к мысли, что компоненты — это чистые функции и возвращение состояния от дочерних компонентов оправдано лишь в крайних случаях.
Про Angular
Я некоторое время занимаюсь разработкой на Angular и использование EDA подхода сильно помогает в создании приложений. Ниже я бы хотел поделиться простой реализацией основных возможностей, описанной выше архитектуры, на примере Angular 1.x
Как обычно, все начинается с разработки сервиса, который определяет некоторые возможности. В нашем случае – генерирование и отлов событий.
Листинг нашего сервиса.
'use strict'; function EventService($rootScope) { /* ----- api нашего сервиса ------*/ this.on = on; this.broadcast = invoke; /* ----- функции для внутреннего использования --------*/ function _on(scope, event, func) { /* ------- создание watcher для scope необходимого компонента ------*/ var off = scope.$on(event, func); /* -------- подчищаем за собой -------*/ scope.$on("$destroy", off); }; function _broadcast(event, params) { if (!params) params = []; params = angular.copy(params); /*------ каррируем исходные параметры ------*/ [event].concat(params); $rootScope.$broadcast.apply($rootScope, params); }; /* ------- используя замыкания, создаем методы генерирования и отлова событий -------*/ function on(handler) { return function(scope, func) { _on(scope, handler, func); }; }; function invoke(handler) { return function() { _broadcast(handler, arguments); }; }; }; EventService.$inject = ['$rootScope'];
Некоторые высказываются, что Angular не приспособлен для реализации подобного рода вещей, мол циклы дайджеста съедают все рабочее время и если необходимо реализовать большое количество возможных событий, то количество watchers, которое понадобится для этого, будет избыточным. Но это все в прошлом и начиная с версии 1.4.х магическое число 2000 давно перевалило за 100к.
Далее, имея такой сервис, можно легко создавать собственный event-manager для отдельно взятого компонента либо группы компонентов.
'use strict'; function EventManager(EventService, EVENTS) { /* ----- набор событий определенного компонента -----*/ var handlers = { onScroll: EVENTS.scroll }; /* ------ установка генератора и листенера событий ------*/ this.onScroll = EventService.on(handlers.onScroll); this.scroll = EventService.broadcast(handlers.onScroll); }; /* ------ централизованное или распределенное хранение событий -------*/ EventManager.$inject = ['EventService', 'EVENTS'];
И собственно примеры использования данного event-manager’a
'use strict'; function ComponentOne(EventManager) { /*----- some code before -----*/ EventManager.scroll(); /*----- some code after -----*/ }; ComponentOne.$inject = ['EventManager']; function ComponentTwo($scope, EventManager) { /*----- some code before -----*/ EventManager.onScroll($scope, cb); function cb(event, params) { /* ---- some code -----*/ }; /*----- some code after -----*/ }; ComponentTwo.$inject = ['$scope', 'EventManager'];
Лично для меня достоинства такого подхода заключаются в сохранении модульности приложения. Всегда можно отследить, что вызывается жестко привязанным, а что отдано на работу событий. Причем использование менеджеров для разных компонентов повышает удобочитаемость кода, что способствует более быстрой отладке.
Спасибо за внимание.
ссылка на оригинал статьи https://habrahabr.ru/post/278619/
Добавить комментарий