0

I have an Angular JS application and I want to do a global action every second when the route changes successfully. So I created a .run() block in which I DI $interval and use the $interval on $routeChangeSuccess. The strange thing is that after each route change, the interval starts fireing faster and faster. This is my code:

app.run(["$interval", "$rootScope", function($interval, $rootScope){

$rootScope.$on("$routeChangeSuccess", function(event, current){
    if(current.$$route.authenticate){
        $interval(function(){
            console.log("whatever");
        }, 1000);
    }

});

}]);

To conclude, the "whatever" console log starts firing faster and faster. Is it because the $interval is a Singleton so it gets recreated each time? But why isn't the old $interval deleted?

Cristi Berceanu
  • 1,693
  • 1
  • 10
  • 12

2 Answers2

0

I don´t understand why you want attach a new interval that is running every second on every routeChange. If I understand it correctly, you want it to check every second obly when route needs authenticate ? If so, you need to cancel the interval if the route is not authenticate anymore.

you need to delete your $interval if you dont want it to be fired anymore.

var stopTime = $interval(DoJob, 1000);

// delete when you dont need it anymore.
$interval.cancel(stopTime);

see documentation for $interval

app.run(["$interval", "$rootScope", function($interval, $rootScope){
var intervalPtr = null;
$rootScope.$on("$routeChangeSuccess", function(event, current){
    //page needs authentication
    //and interval was not set yet.
    if(current.$$route.authenticate && intervalPtr === null){
        intervalPtr = $interval(function(){
            console.log("whatever");
        }, 1000);
    // page that does not need authentication
    // reset only of there is a interval running
    } else if (intervalPtr !== null) {
         $interval.cancel(intervalPtr);
         intervalPtr = null;
    }

});

}]);
Luke
  • 8,235
  • 3
  • 22
  • 36
  • I have a service inside the interval which tests the user's innactivity.(**document.onmousemove**, **document.onkeypress**, **document.onclick**) so I verify every second and reset the counter if any of those actions happened. I only use it for authenticated routes because I logout the user if the inactivity is longer than 5 mins. The service that tests the inactivity is DI so it didn't made any sense to show it here since it doesn't affect the issue in any way. Your answer wouldn't work since I have a lot of routes with authenticate and only 1-2 with with no authentification(so far).@Luke – Cristi Berceanu May 28 '14 at 14:41
  • why not? you want to check users inactivity only on routes that need authentication, right? if the user is on a page, that has no authentication, you can stop the interval. and if the user is on any page that needs the authentication, the interval works, and should be created if it does not exist already – Luke May 28 '14 at 14:44
  • btw, i made a little change as i forgot something in the first `if` clause – Luke May 28 '14 at 14:45
  • Yes, but the only page that doesn't need authenticate is the login page and recover password page. All other pages need authentication. So if the user moves through(let's say) 20 pages that need authentication, the script would have the same problem as before. – Cristi Berceanu May 28 '14 at 14:47
  • no, please try the example that is the most up to date. my solution right now should work for you as you expect. – Luke May 28 '14 at 14:48
  • btw you want to cancel the timer if the user is on the login page or recover password page, otherwise you will get weird logout trys even though the user is on a page that does not need authentication – Luke May 28 '14 at 14:50
  • Yes :) I read it again after refresh and it makes sense. I'll try it, but I'm sure it'll work :P – Cristi Berceanu May 28 '14 at 14:51
  • Your answer was almost perfect. You need to destroy the interval in the first `if`, because it will only start after 2 route changes, and then destroy the interval if you weren't logged in. so just add `$interval.cancel(intervalPtr);intervalPtr = null;` to the first condition and remove the `intervalPtr === null` so it'll delete the $interval permanently if you are logged out – Cristi Berceanu May 28 '14 at 15:10
0

On the $interval doc :

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.

So don't forget to cancel the previous $interval before creating a new one :

app.run(["$interval", "$rootScope", function($interval, $rootScope){
var interval = null;

$rootScope.$on("$routeChangeSuccess", function(event, current){
      $interval.cancel(interval);        
      if(current.$$route.authenticate){
        interval = $interval(function(){
            console.log("whatever");
        }, 1000);
    }

});

}]); 
Riron
  • 1,023
  • 14
  • 18
  • 1
    This will not work correctly, as if you change the route to something different than `authenticate` the interval will still run... so on a page where authentication is not needed, it would still check – Luke May 28 '14 at 14:35