Остановить $timeout при запуске нового контроллера

Я опрашиваю свои данные каждые 2 секунды, чтобы они обновлялись на странице. Моя проблема в том, что когда я захожу на другую страницу, тайм-аут остается активным. Как я могу отменить тайм-аут при посещении новой страницы?

function IndexCtrl($scope, $timeout, RestData) {
    $scope.rd = {};

    (function getRestDataFromServer() {
        RestData.query(function(data){
            $scope.rd = data;
            $timeout(getRestDataFromServer, 2000);
        });
    })();
}

// РЕДАКТИРОВАТЬ Я нашел решение, но не уверен, что оно хорошее. Когда я сохраняю тайм-аут в $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); 
}

person fraherm    schedule 16.06.2013    source источник
comment
ты пробовал $timeout.cancel()?   -  person Ivan Chernykh    schedule 16.06.2013


Ответы (2)


Есть несколько событий Angular, которые транслируются при изменении маршрута. Вы можете прослушивать их в IndexCtrl с помощью $scope.$on и действовать соответственно:

Событие $destroy

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() для отмены тайм-аута.

person Stewie    schedule 17.06.2013
comment
Спасибо! Это именно то, что я искал. знак равно - person fraherm; 17.06.2013
comment
На самом деле это $timeout.cancel(обещание). - person David Bennett; 11.07.2013

Ответ Стьюи идеален. Я просто хотел поделиться этой простой вспомогательной функцией, которую я использую вместо прямого использования $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) очищает этот больше не нужный слушатель, как только истечет время ожидания.

person Eric Simonton    schedule 13.06.2014
comment
Это звучит как очень хорошее решение. Не могли бы вы поделиться всем кодом, например, рабочим примером, включая определение службы, чтобы мне, как новичку, было проще интегрировать его в собственное приложение? Спасибо! - person SHernandez; 24.06.2014
comment
Меня какое-то время смущала переменная deregister, я думал, что это функция для отмены тайм-аута, но это не так. Это функция отмены отмены тайм-аута. - person dshepherd; 22.03.2016
comment
@dshepherd, пожалуйста, объясни, потому что я все еще в замешательстве. - person natanavra; 27.09.2016
comment
Если бы переменная была названа deregisterDestroyListener, что могло бы помочь? - person dshepherd; 28.09.2016