SergejKasper
1/18/2014 - 7:26 PM

Publish/subscribe for external service angular

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);
  };
  
}]);