Publish/subscribe for external service angular
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
<div ng-app="app">
<div ng-controller="Ctrl">
<h1>result impl1: {{data1}}</h1>
<h1>result impl2: {{data2}}</h1>
<input type="button" ng-click="cl()" value="Bind1">
<input type="button" ng-click="cl2()" value="Bind2">
<input type="button" ng-click="cl3()" value="Unsub2">
</div>
</div>
</body>
</html>
var App = {};
App.Factory = function Parent() {
var subUid = -1;
var myvar = 0;
var impls = {};
var publish = function(subject){
impls[subject].subscribers.forEach(function(o){
o.func.apply(this, [impls[subject].child.get_i()]);
});
};
return {
getChild: function Child(childName) {
if(childName){
if(!impls.hasOwnProperty(childName)){
var thisChild = {
name: childName,
inc: function inc() {
myvar ++;
console.log('i is: ' + myvar);
},
get_i: function inc() {
return myvar;
}
};
impls[childName] = {child: thisChild, subscribers: []};
console.log('new child: ' + impls[childName].child.name);
}
return impls[childName].child;
}else{
throw {error: 'no name given'};
}
},
subscribe: function(event, func){
var token = ( ++subUid ).toString();
impls[event].subscribers.push({token: token , func: func});
return token;
},
unsubscribe: function(event, token){
var removed = false;
impls[event].subscribers.some(function(sub, i){
console.log('sub ' + sub + 'token ' + sub.token + 'compare ' + token );
if(sub && sub.hasOwnProperty('token') && sub.token === token){
console.log('del' + i);
impls[event].subscribers.splice( i, 1 );
removed = true;
return removed;
}
});
return removed;
},
act: function(action, func){
var childName = action;
impls[childName].child.inc();
setTimeout(function(){
//select relevant observers (mock)
publish(childName);
}, 200);
}
};
};
angular.module('app', []).config([
'$provide', function($provide) {
return $provide.decorator('$rootScope', [
'$delegate', function($delegate) {
$delegate.safeApply = function(fn) {
var phase = $delegate.$$phase;
if (phase === "$apply" || phase === "$digest") {
if (fn && typeof fn === 'function') {
fn();
}
} else {
$delegate.$apply(fn);
}
};
return $delegate;
}
]);
}
]).service('context', function(){
var a = App.Factory();
a.getChild('aImpl');
a.getChild('bImpl');
return{
subscribe: function(handler, func){
return a.subscribe(handler, func);
},
unsubscribe: function(handler, token){
return a.unsubscribe(handler, token);
},
act: function(actor){
a.act(actor);
}
};
}).controller('Ctrl', ['$scope', '$rootScope', 'context', function SecondCtrl($scope, $rootScope, context) {
var sub1 = context.subscribe('aImpl', function(result){
$rootScope.safeApply(function(){
$scope.data1 = result;
});
});
var sub2 = context.subscribe('bImpl', function(result){
$rootScope.safeApply(function(){
$scope.data2 = result;
});
});
$scope.cl = function(){
context.act('aImpl');
};
$scope.cl2 = function(){
context.act('bImpl');
};
$scope.cl3 = function(){
context.unsubscribe('bImpl', sub2);
};
}]);