Подтвердить что ты не робот

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); 
}
4b9b3361

Ответ 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) очищает этот ненужный прослушиватель, как только истечет время ожидания.