Reputation: 425
Good afternoon,
I've been struggling with an unfamiliar problem. But first let me explain what I'm trying to achieve.
Purpose
What I'm trying to do is, setting a timer on each view, so if the internet connection is slow the timer calls a function which displays an ionicPopup with the question: "Would you like to refresh the view?" combined with a refresh button. When the button is clicked, the view will refresh. If the view loads in time (I've set the timer on 10000 milliseconds), the $timeout.cancel action is being called and the timer stops.
If that would be all it would be working fine at the moment.
Problem
If I navigate through my main pages rapidly, it looks like the timers aren't stop and the "Refresh popup" pops up on another page. That only happens when you click through at high speed. It looks like a few popup pop up at once beneath each other. I don't know what might be the problem, but I guess that the $timeout.cancel isn't being called if you navigate through the pages to quickly.
Code
Service
.factory('Timer', function ($ionicPopup, $state, $timeout) {
return {
start: start
};
function start() {
return $timeout(showPopup, 10000);
}
function showPopup() {
$ionicPopup.show({
title: 'Slow internetconnection',
template: 'Click refresh to try again.',
buttons: [
{
text: 'Refresh',
onTap: function (e) {
$state.reload()
}
}
]
})
}
})
Controller
.controller('HomeCtrl', function ($scope, Request, Timer, $timeout) {
var timer = Timer.start();
Request.execute().finally(function () {
$timeout.cancel(timer);
})
$scope.$on('$destroy', function () {
$timeout.cancel(timer);
});
})
I hope my problem is understandable.
Upvotes: 0
Views: 202
Reputation: 3096
The key thing to note here is:
If I navigate through my main pages rapidly, it looks like the timers aren't stop and the "Refresh popup" pops up on another page.
As you navigate through, your ionic views are created/destroyed, and therefore you lose references to timer
objects.
So, in controllers where you are using timers, you must invalidate the timer before you leave that page. This is because timers are wrappers around JavaScript's setTimeout
and setInterval
, and JavaScript has method level scope that passes the method as a parameter to setInterval
which will hold a reference to it, while your controller gets destroyed. Therefore, when you change view, although your controller instance may get removed, the timer does not.
Add $ionicView.afterLeave
callbacks in your controllers.
$scope.$on("$ionicView.afterLeave", function(event, data){
$timeout.cancel(timer);
});
This will cancel the timer for a particular controller, after that controller's view is dismissed.
Upvotes: 3