AngularJS Mediator Pattern

Sinopse

Um padrão de mediador padrão aplicado a AngularJS que não usa $broadcasts ou $emits.

  • Evita injetar e expor desnecessariamente $scopea visão onde controllerAsfor preferível.
  • Contorna o uso de $rootScopepara atualizar os modelos de visão existentes nos $scopecaminhos irmãos .
  • Não aciona ciclos $applyou adicionais $digest.
  • Emprega lodash para melhor desempenho entre navegadores.
  • Mediator.subscriberetorna uma função para cancelar o registro do assinante, semelhante à $scope.$onimplementação do Angular .

( function( angular , _ ) {
function MediatorService( $log ) {
var Mediator = {};

var channels = {};
var subscriberId = 0;


Mediator.publish = function( channel , publisher , data ) {
if ( ! hasSubscriber( channel ) ) {
return;
}

var subscribers = channels[ channel ];

_
.map( subscribers, function( subscriber ) {
try {
subscriber
.callback( data );
} catch ( e ) {
$log
.error( e , publisher , subscriber.name )
}
} );
};


Mediator.subscribe = function( channel , subscriber , callback ) {
if ( ! hasSubscriber( channel ) ) {
channels
[ channel ] = [ ];
}

channels
[ channel ].push( {
"callback" : callback ,
"name" : subscriber ,
"subscriberId" : ++subscriberId
} );

return function( ) {
unsubscribe
( subscriberId );
};
};


function hasSubscriber( channel ) {
return _.has( channels , channel );
}


function unsubscribe( subscriberId ) {
channels
= _.map( channels , function( channel ) {
return _.filter( channel , function( subscriber ) {
return subscriber.subscriberId !== subscriberId;
});
});
}

return Mediator;
}

angular

.module( "app" )
.factory( "Mediator" , [ "$log" , MediatorService ] );

} ) ( angular, _ );

Implementação

Plnkr

HTML

<div data-first=""></div>
<div data-second=""></div>

JS

angular
.module( "app" , [ ] )
.factory( "Mediator" , [ "$log", MediatorService ] )
.directive( "first" , function( ) {
return {
controller
: function( ) {
this.name = "First";
},
controllerAs
: "first",
template: "<p ng-bind='first.name'></p><div data-third></div>"
};
} )
.directive( "second" , function( Mediator ) {
return {
controller
: function( ) {
this.name = "Second";
this.publishNewName = Mediator.publish.bind( this , "NewName" , "second" , this.name );
},
controllerAs
: "second",
template: "<a ng-bind='second.name' ng-click='this.publishNewName( )'></a>"
};
} )
.directive( "third" , function( Mediator ) {
return {
controller
: function( ) {
this.name = "Third";
var unsubscribe = Mediator.subscribe( "NewName" , "third" , setName.bind( this ) );

function setName(name) {
this.name = name;
unsubscribe
( );
}
},
controllerAs
: "third",
template: "<p ng-bind='third.name'></p>"
};
} );