Angular multiple instances of the same controller are created

1.2k views Asked by At

In my example below you can see that each time you go to a page a new instance of the same controller is created with a different id, and the old one is not destroyed, the setIntervat method keeps logging the corresponding scope id and fruit name on all of them. Let's say I have an ajax call instead of the log, that refreshes the page's content from time to time, but I don't want to make calls for the inactive pages, how can I fix this?

example

var app = angular.module('plunker', ['ngRoute']);

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/fruit/:fruitId', {
      templateUrl: 'fruit-tpl.html',
      controller: 'FruitController'
    })
    .otherwise({
      redirectTo: '/fruit/1'
    });
}]);

app.controller('FruitController', ['$scope', '$routeParams',
  function($scope, $routeParams) {
    var fruitArr = ['Lemons', 'Oranges', 'Grapefruit'],
        fruitId = $routeParams.fruitId - 1;

    $scope.fruitName = fruitArr[fruitId];

    setInterval(function() {
      console.log('scope', $scope.$id, $scope.fruitName);
    }, 3000);
  }
]);
1

There are 1 answers

0
Kevin B On

setInterval does not get stopped automatically when a controller is destroyed, and until it is stopped, the variables closed on by the closure you pass to it will remain in memory. Even if you switched to $interval, the same problem would persist.

Note: Intervals created by this service must be explicitly destroyed when you are finished with them. In particular they are not automatically destroyed when a controller's scope or a directive's element are destroyed. You should take this into consideration and make sure to always cancel the interval at the appropriate moment. See the example below for more details on how and when to do this.

var theInterval = setInterval(function() {
  console.log('scope', $scope.$id, $scope.fruitName);
}, 3000);
$scope.$on('$destroy', function() {
  // Make sure that the interval is destroyed too
  clearInterval(theInterval);
});