Como limpar ou parar o timeInterval no angularjs?

91

Estou fazendo uma demonstração na qual estou obtendo dados do servidor após intervalos regulares de tempo usando $intervalAgora, preciso parar / cancelar isso.

Como posso conseguir isso? Se eu precisar reiniciar o processo, como devo fazer isso?

Em segundo lugar, tenho mais uma pergunta: estou obtendo dados do servidor após reqular intervalos de tempo. Existe alguma necessidade de usar $scope.applyou $scope.watch?

Aqui está o meu êmbolo:

  app.controller('departureContrl',function($scope,test, $interval){
   setData();

   $interval(setData, 1000*30);

   function setData(){
      $scope.loading=true;
    test.stationDashBoard(function(data){
        console.log(data);
        $scope.data=data.data;
        $scope.loading=false;
        //alert(data);
    },function(error){
        alert('error')
    }) ;

   }
});

http://plnkr.co/edit/ly43m5?p=preview

user944513
fonte

Respostas:

158

Você pode armazenar a promessa retornada pelo intervalo e usar $interval.cancel()para essa promessa, o que cancela o intervalo dessa promessa. Para delegar o início e a parada do intervalo, você pode criar start()e stop()funções sempre que quiser interrompê-los e reiniciá-los a partir de um evento específico. Eu criei um trecho abaixo mostrando o básico para iniciar e parar um intervalo, implementando-o na visualização por meio do uso de eventos (por exemplo ng-click) e no controlador.

angular.module('app', [])

  .controller('ItemController', function($scope, $interval) {
  
    // store the interval promise in this variable
    var promise;
  
    // simulated items array
    $scope.items = [];
    
    // starts the interval
    $scope.start = function() {
      // stops any running interval to avoid two intervals running at the same time
      $scope.stop(); 
      
      // store the interval promise
      promise = $interval(setRandomizedCollection, 1000);
    };
  
    // stops the interval
    $scope.stop = function() {
      $interval.cancel(promise);
    };
  
    // starting the interval by default
    $scope.start();
 
    // stops the interval when the scope is destroyed,
    // this usually happens when a route is changed and 
    // the ItemsController $scope gets destroyed. The
    // destruction of the ItemsController scope does not
    // guarantee the stopping of any intervals, you must
    // be responsible for stopping it when the scope is
    // is destroyed.
    $scope.$on('$destroy', function() {
      $scope.stop();
    });
            
    function setRandomizedCollection() {
      // items to randomize 1 - 11
      var randomItems = parseInt(Math.random() * 10 + 1); 
        
      // empties the items array
      $scope.items.length = 0; 
      
      // loop through random N times
      while(randomItems--) {
        
        // push random number from 1 - 10000 to $scope.items
        $scope.items.push(parseInt(Math.random() * 10000 + 1)); 
      }
    }
  
  });
<div ng-app="app" ng-controller="ItemController">
  
  <!-- Event trigger to start the interval -->
  <button type="button" ng-click="start()">Start Interval</button>
  
  <!-- Event trigger to stop the interval -->
  <button type="button" ng-click="stop()">Stop Interval</button>
  
  <!-- display all the random items -->
  <ul>
    <li ng-repeat="item in items track by $index" ng-bind="item"></li>
  </ul>
  <!-- end of display -->
</div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

Ryeballar
fonte
@ obrigado pela resposta .. há alguma necessidade de adicionar aplicar ou observar quando estou buscando dados do intervalo de tempo de reqular do serviço
user944513
Não, você não precisa usar apply(), se estiver usando o $intervalserviço, já que ele faz isso por você. Mas se você estiver usando o integrado setInterval(), talvez seja necessário usar $scope.$apply().
Ryeballar
Muito boa solução. O $destroyfunciona bem em conjunto com o http-auth-interceptorcomo no meu caso eu quero parar o intervalo durante o auth falha (como sessão expirada) e começar de novo depois auth succesfull. Obrigado por esta excelente solução.
Neel
37
var interval = $interval(function() {
  console.log('say hello');
}, 1000);

$interval.cancel(interval);
Arun Sharma
fonte
9
var promise = $interval(function(){
    if($location.path() == '/landing'){
        $rootScope.$emit('testData',"test");
        $interval.cancel(promise);
    }
},2000);
Jijo Paulose
fonte
Como os URLs podem mudar no futuro, eu pensaria duas vezes antes de usar o $location.path()nome do estado e não o nome
Or Duan
1
    $scope.toggleRightDelayed = function(){
        var myInterval = $interval(function(){
            $scope.toggleRight();
        },1000,1)
        .then(function(){
            $interval.cancel(myInterval);
        });
    };
Christian Bonato
fonte
1

Quando você deseja criar uma promessa de armazenamento de intervalo para variável:

var p = $interval(function() { ... },1000);

E quando quiser parar / limpar o intervalo, basta usar:

$interval.cancel(p);
pixparker
fonte