2013-06-16 3 views
27

Sto interrogando i miei dati ogni 2 secondi per tenerli aggiornati sulla pagina. Il mio problema è quando visito un'altra pagina il timeout rimane attivo. Come posso cancellare il mio timeout quando visito una nuova pagina?

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

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

// EDIT ho trovato una soluzione, ma non sono sicuro se è un buon compromesso. Quando salgo il timeout su $ rootScope, posso cancellarlo in tutti gli altri controller.

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); 
} 
+0

hai provato '$ timeout.cancel()'? – Cherniv

risposta

64

Ci sono un paio di eventi Angolari che vengono trasmessi quando il percorso viene modificato. È possibile ascoltare per loro all'interno del IndexCtrl utilizzando $scope.$on e agire di conseguenza:

$ distruggere evento

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() restituisce un oggetto promessa. Questo oggetto può essere fornito alla funzione $timeout.cancel() per annullare il timeout.

+0

Grazie! Questo è esattamente quello che stavo cercando. =) – fraherm

+0

In realtà, è $ timeout.cancel (promessa). –

+0

Questo è corretto. Grazie per averlo notato. Risposta aggiornata – Stewie

15

La risposta di Stewie è perfetta. Volevo solo condividere questa semplice funzione di supporto che uso invece di usare $timeout direttamente, in modo che non ho mai pensare a questo problema ancora:

function setTimeout(scope, fn, delay) { 
    var promise = $timeout(fn, delay); 
    var deregister = scope.$on('$destroy', function() { 
     $timeout.cancel(promise); 
    }); 
    promise.then(deregister, deregister); 
} 

ho aggiunto questa funzione per un servizio chiamato miscUtils, e mi inietto quel servizio invece di iniettare $timeout. Quindi, per esempio, per fare una funzione di "aggiornamento" che viene eseguito ogni 30 secondi fino a quando $scope è distrutto:

update(); 
function update() { 
    // do the actual updating here 
    miscUtils.setTimeout($scope, update, 30000); 
} 

Modifica per coloro confuso su ciò che sta succedendo con deregister:

Questo la funzione registra un listener per l'evento $destroy, ma una volta completato il timeout non è più necessario; non c'è più un timeout da cancellare. scope.$on restituisce una funzione che, quando viene chiamata, cancella l'ascoltatore. Quindi, promise.then(deregister) pulisce quel listener non più necessario non appena termina il timeout.

+0

Sembra un'ottima soluzione. Potresti condividere tutto il codice, come un esempio funzionante, includendo la definizione del servizio, quindi per me come principiante è più facile integrarlo nella mia applicazione? Grazie! – SHernandez

+0

La variabile 'deregister' mi ha confuso per un po ', ho pensato che fosse la funzione per cancellare il timeout ma non lo è. È la funzione per annullare l'annullamento del timeout. – dshepherd

+0

@dshepherd si prega di spiegare perché sono ancora confuso. – natanavra