Angular js subscribe multiple times and fire multiple events

1.6k views Asked by At

I am working for an application and I want to communicate Angular js with a third party js library. For this I have used pubsub method using mediator js. But due to this when I subscribe to any event then it subscribe multiple times and due to this when I publish event, it fires multiple times.

I have used below code:

angular.module('app')
   .service('mediator', function() {
     var mediator = window.mediator || new Mediator();
     return mediator;
 });

// Main controller begins here
  angular.module('app').controller('MainController', MainController);
  MainController.$inject = ['mediator'];

  function MainController(mediator){
    var vm = this;
    vm.title = "This is main controller."

    vm.sendMessage = function(){
      mediator.publish('something', { data: 'Some data' });  
    }


  }


  // First page controller begins here
   angular.module('app').controller('FirstController', FirstController);
  FirstController.$inject = ['mediator'];

  function FirstController(mediator){
    var vm = this;

    console.log('Subscribed events for first controller.');

    var counter = 0;
    mediator.subscribe('something', function(data){ 
      console.log('Fired event for '+ counter.toString());
      counter = counter + 1;
    });

  }

Here is the plunker for better explanation: Plunkr

To test this plunker:

  1. Run plunker.
  2. Open developer console.
  3. Click on First page
  4. Click fire event
  5. Click on second page
  6. Click on first page
  7. Click on fire event

As you navigate to first page second time, it will subscribe for event again and will fire twice. This will subscribe multiple time when you navigate to first page multiple times.

Please let me know if I am doing something wrong.

1

There are 1 answers

2
Ovidiu Dolha On BEST ANSWER

You could unsubscribe when the controller is destroyed.

To do this using mediator, you first need to save subscription function:

var sub = function(data){ 
  console.log('Fired event for '+ counter.toString());
  counter = counter + 1;
}
mediator.subscribe('something', sub);

Then you can use the angular event to unsubscribe from the notifications when the controller is removed:

$scope.$on("$destroy", function() {
    mediator.remove("something", sub);
});

Whenever using this pattern, you should consider the moments when a subscription needs to be removed, not only for duplication reasons, but also it can cause memory leaks.

Don't forget you also need to inject $scope (even if not using it as a holder of model, it's fine to use it for registering event listeners):

angular.module('app').controller('FirstController', FirstController);
FirstController.$inject = ['mediator', '$scope'];

Plunkr example: https://plnkr.co/edit/CgYLLSxGF2Fww5vBB7PB

Hope it helps.