Stop $timeout при запуске нового контроллера
Я просматриваю свои данные каждые 2 секунды, чтобы их обновлять на странице. Моя проблема в том, что когда я посещаю другую страницу, тайм-аут остается активным. Как я могу отменить свой тайм-аут при посещении новой страницы?
function IndexCtrl($scope, $timeout, RestData) {
$scope.rd = {};
(function getRestDataFromServer() {
RestData.query(function(data){
$scope.rd = data;
$timeout(getRestDataFromServer, 2000);
});
})();
}
//EDIT
Я нашел решение, но не уверен, что он хороший. Когда я сохраняю свой тайм-аут в $rootScope, я могу отменить его во всех других контроллерах.
function IndexCtrl($scope, $rootScope, $timeout, RestData) {
$scope.rd = {};
(function getRestDataFromServer() {
RestData.query(function(data){
$scope.rd = data;
$rootScope.prom = $timeout(getRestDataFromServer, 2000);
});
})();
}
function newPageCtrl($scope, $rootScope, $timeout) {
$timeout.cancel($rootScope.prom);
}
Ответы
Ответ 1
Есть несколько событий Angular, которые транслируются при изменении маршрута. Вы можете слушать их в IndexCtrl
с помощью $scope.$on
и действовать соответственно:
$destroy event
var promise = $timeout(getRestDataFromServer, 2000);
...
$scope.$on('$destroy', function(){
$timeout.cancel(promise);
});
$locationChangeStart
var promise = $timeout(getRestDataFromServer, 2000);
...
$scope.$on('$locationChangeStart', function(){
$timeout.cancel(promise);
});
$timeout()
возвращает объект обещания. Этот объект может быть отправлен в функцию $timeout.cancel()
для отмены таймаута.
Ответ 2
Ответ Стьюи идеален. Я просто хотел поделиться этой простой вспомогательной функцией, которую я использую, вместо непосредственного использования $timeout
, так что мне больше не придется думать об этой проблеме:
function setTimeout(scope, fn, delay) {
var promise = $timeout(fn, delay);
var deregister = scope.$on('$destroy', function() {
$timeout.cancel(promise);
});
promise.then(deregister, deregister);
}
Я добавил эту функцию в службу под названием miscUtils
, и я вставляю эту службу вместо инъекции $timeout
. Затем, например, для создания функции "обновления", которая запускается каждые 30 секунд до тех пор, пока $scope
не будет уничтожен:
update();
function update() {
// do the actual updating here
miscUtils.setTimeout($scope, update, 30000);
}
Изменить для тех, кто запутался в том, что происходит с deregister
:
Эта функция регистрирует прослушиватель для события $destroy
, но как только тайм-аут завершен, он больше не нужен; больше нет времени для отмены. scope.$on
возвращает функцию, которая при вызове отменяет этот прослушиватель. Таким образом, promise.then(deregister)
очищает этот ненужный прослушиватель, как только истечет время ожидания.