title: AngularJS: Listen to events, one after the other
body: <p>is there an angular-way to listen for events that occur one after the other? For example, I want to listen on a <code>$rootScope</code> for the <code>$routeChangeSuccess</code> and the <code>$viewContentLoaded</code> event. When the first event occurs, and after that, the second event occurs, I want to call a callback.</p>
  
  <p>Is this possible? Or do I have to write it on my own? It would also be nice to configure if the order of the events is important or not. Or any ideas, how to implement such a behaviour?</p>
  
  <p><strong>Update</strong></p>
  
  <p>Because I haven't found anything on the web, I came up with my own solution. I think it works, but I don't know if there are any drawbacks with this method.</p>
  
  <p>And any suggestions how to integrate this global into an AngularJS project? Or even as a bower component? Should I attach the function to a scope, or to the rootScope? Any help is appreciated!</p>
  
  <p>Here is the Plunker link and the code: <a href="http://plnkr.co/edit/slfvUlFCh7fAlE4IPt8o?p=preview" rel="nofollow">http://plnkr.co/edit/slfvUlFCh7fAlE4IPt8o?p=preview</a></p>
  
  <pre><code>var app = angular.module('plunker', []);
  
  app.controller('MainCtrl', function($scope) {
    $scope.events = [];
  
    var successiveOn = function(events, eventScope, callback, orderImportant) {
      // array for the remove listener callback
      var removeListenerMethods = [];
      // events array that is passed to the callback method
      var eventsArr = [];
      // how many events are fired
      var eventCount = 0;
      // how many events should be fired
      var targetEventCount = events.length;
      // track the next event, only for orderImportant==true
      var nextEvent = events[0];
      // iterate over all event strings
      for (var i = 0; i &lt; events.length; i++) {
        var event = events[i];
        // attach an $on listener, and store the remove listener function
        var removeListener = eventScope.$on(event, function(evt) {
          if (evt.name == nextEvent || !orderImportant) {
            ++eventCount;
            nextEvent = events[eventCount];
            eventsArr.push(evt);
            // if all events has fired, call the callback method and reset
            if (eventCount &gt;= targetEventCount) {
              callback(eventsArr);
              nextEvent = events[0];
              eventCount = 0;
              eventsArr = [];
            }
          }
        });
        removeListenerMethods.push(removeListener);
      }
  
      // the return function is a anonymous function which calls all the removeListener methods
      return function() {
        for (var i = 0; i &lt; removeListenerMethods.length; i++) {
          removeListenerMethods[i]();
        }
      }
    }
  
    // order is unimportant
    var removeListeners = successiveOn(["orderUnimportant1", "orderUnimportant2", "orderUnimportant3"], $scope, function(events) {
      var str = "Events in order of trigger: ";
      for (var i = 0; i &lt; events.length; i++) {
        str += events[i].name + ", ";
      }
      $scope.events.push(str);
    }, false);
  
    $scope.$broadcast("orderUnimportant1");
    $scope.$broadcast("orderUnimportant2");
    $scope.$broadcast("orderUnimportant3"); // Events were triggered 1st time
  
    $scope.$broadcast("orderUnimportant3");
    $scope.$broadcast("orderUnimportant2");
    $scope.$broadcast("orderUnimportant1"); // Events were triggered 2nd time, order doesn't matter
    removeListeners();
  
    // order is important!
    var removeListeners = successiveOn(["OrderImportant1", "OrderImportant2", "OrderImportant3"], $scope, function(events) {
      var str = "Events in order of trigger: ";
      for (var i = 0; i &lt; events.length; i++) {
        str += events[i].name + ", ";
      }
      $scope.events.push(str);
    }, true);
  
    $scope.$broadcast("OrderImportant1");
    $scope.$broadcast("OrderImportant2");
    $scope.$broadcast("OrderImportant3"); // Events were triggered
  
    $scope.$broadcast("OrderImportant1");
    $scope.$broadcast("OrderImportant3");
    $scope.$broadcast("OrderImportant2"); // Events were NOT triggered
    removeListeners();
  });
  </code></pre>