Mahmoud
Mahmoud

Reputation: 864

Controller life-cycle in Angular

I defined m my application states using ui-router:

$stateProvider
  .state('app', {
    abstract: true,
    views: {
      'nav@': {
        templateUrl: 'app/navbar.html',
        controller: 'NavbarController',
        controllerAs: 'vm'
      },
      'main@': {
        template: '<div ui-view></div>'
      }
    }
  })
  .state('child1', {
    url: '/child1',
    parent: 'app',
    templateUrl: 'app/child1.html',
    controller: function($timeout) {
      $timeout(function() {
        alert('from child_1');
      }, 15000)
    },
    controllerAs: 'vm'
  })
  .state('child2', {
    url: '/child2',
    parent: 'app',
    templateUrl: 'app/child2.html',
    controller: 'ctrl_2',
    controllerAs: 'vm'
  })

When I go from /child1 to /child2 quickly (before 15000 miliseconds), still I see the alert that was defined in child1 controller, is this a normal behavior?

Upvotes: 0

Views: 216

Answers (1)

georgeawg
georgeawg

Reputation: 48968

is this a normal behavior?

Yes, this is normal behavior. Function references created and given to another function (such as the $timeout service) will last as long as the other function keeps that reference. In the case of the $timeout service, it will keep that reference for the duration of the timeout (in this case 15 seconds).

In addition if the child function uses local variables of the parent function, those local variables will be retained for the life of the child function. That process is known as "creating a closure".

For more information, see MDN JavaScript Reference - Closures

The $timeout service needs to be told to cancel the timeout and remove the reference or it will persist beyond the life of the controller.

controller: function($timeout, $scope) {
  var promise = $timeout(function() {
    alert('from child_1');
  }, 15000);
  $scope.$on("$destroy", function() {
    promise.cancel();
  });
},

In the above example, the $timeout service attaches a function called cancel to the promise that it returns. Client code can invoke that function to tell the $timeout service to abort the timeout and release the reference to the function.

When the ui-router switches from child1 state to another state, it destroys the scope of the controller. The controller should listen for the $destroy event and cancel the timeout.

Upvotes: 2

Related Questions