
EDA - event driven architecture or event-oriented architecture. A fairly well-known approach to designing web applications, which greatly simplifies development when related components are located on different branches of the hierarchy, making their communication more transparent.
')
Speaking of components. Angular only recently acquired its real components, but the implementation of this approach was possible earlier, with the help of simple and nested directives.
About EDA
As Wikipedia tells us, an event in EDA can be defined as a “significant state change.” It is known that components in most frameworks that are directly related, can easily inherit and transmit the state that determines their behavior. Moreover, Angular, which implements the unloved two-way binding by everyone, does not have any problems with this. But all the promises of the development team say that this is not good and you need to get used to the idea that the components are pure functions and the return of the state from the child components is justified only in extreme cases.
Pro angular
I’ve been working on Angular for a while and using the EDA approach helps a lot in building applications. Below I would like to share a simple implementation of the basic features of the above architecture, using the example of Angular 1.x
As usual, it all starts with developing a service that identifies some of the features. In our case - the generation and trapping of events.
Listing our service.
'use strict'; function EventService($rootScope) { this.on = on; this.broadcast = invoke; function _on(scope, event, func) { var off = scope.$on(event, func); scope.$on("$destroy", off); }; function _broadcast(event, params) { if (!params) params = []; params = angular.copy(params); 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'];
Some people say that Angular is not suitable for implementing this kind of things, saying that digest cycles eat up all the working time and if you need to implement a large number of possible events, the number of watchers that will be needed for this will be redundant. But this is all in the past and since version 1.4.x, the magic number 2000 has long exceeded 100k.
Further, having such a service, you can easily create your own event-manager for a single component or group of components.
'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'];
And actually examples of using this event-manager
'use strict'; function ComponentOne(EventManager) { EventManager.scroll(); }; ComponentOne.$inject = ['EventManager']; function ComponentTwo($scope, EventManager) { EventManager.onScroll($scope, cb); function cb(event, params) { }; }; ComponentTwo.$inject = ['$scope', 'EventManager'];
For me personally, the merits of this approach are to preserve the modularity of the application. You can always keep track of what is caused tightly tied, and what is given to the work of events. Moreover, the use of managers for different components increases the readability of the code, which contributes to faster debugging.
Thanks for attention.