2013-06-16 24 views
27

Ich suche alle 2 Sekunden nach meinen Daten, um sie auf der Seite zu aktualisieren. Mein Problem ist, wenn ich eine andere Seite besuche, bleibt das Timeout aktiv. Wie kann ich meine Zeitüberschreitung abbrechen, wenn ich eine neue Seite besuche?

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

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

// EDIT fand ich eine Lösung, aber ich bin nicht sicher, ob es ein gutes ist. Wenn ich mein Timeout im $ rootScope abspeichere, kann ich es in allen anderen Controllern abbrechen.

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

hast du '$ timeout.cancel()' ausprobiert? – Cherniv

Antwort

64

Es gibt einige Winkelereignisse, die gesendet werden, wenn die Route geändert wird. Sie können innerhalb der IndexCtrl für sie hören $scope.$on verwenden und entsprechend handeln:

$ zerstören Ereignis

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() gibt ein Versprechen Objekt. Dieses Objekt kann an $timeout.cancel() Funktion geliefert werden, um die Zeitüberschreitung zu löschen.

+0

Danke! Genau das habe ich gesucht. =) – fraherm

+0

Eigentlich ist es $ timeout.cancel (Versprechen). –

+0

Das ist richtig. Danke, dass du es bemerkst. Antwort aktualisiert – Stewie

15

Stewie Antwort ist perfekt. Ich wollte nur diese einfache Hilfsfunktion teilen, die es nicht direkt mit $timeout verwenden, so dass ich nie wieder über dieses Thema nachdenken:

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

ich diese Funktion zu einem Dienst hinzugefügt genannt miscUtils, und ich spritze dieser Dienst anstelle der Injektion $timeout. Dann zum Beispiel ein „Update“ -Funktion zu machen, die alle 30 Sekunden läuft bis $scope zerstört wird:

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

bearbeiten für diejenigen verwirrt darüber, was mit deregister los ist:

Diese Die Funktion registriert einen Listener für das Ereignis $destroy, aber sobald die Zeitüberschreitung abgeschlossen ist, ist sie nicht mehr erforderlich. Es gibt keine Zeitüberschreitung mehr zum Abbrechen. scope.$on gibt eine Funktion zurück, die den Listener abmeldet, wenn sie aufgerufen wird. So bereinigt promise.then(deregister) den nicht mehr benötigten Listener, sobald die Zeitüberschreitung abgeschlossen ist.

+0

Das klingt nach einer sehr guten Lösung. Könnten Sie den gesamten Code teilen, wie ein Arbeitsbeispiel, einschließlich der Service-Definition, so dass es für mich als Anfänger einfacher ist, es in meine eigene Anwendung zu integrieren? Vielen Dank! – SHernandez

+0

Die 'Deregister'-Variable verwirrte mich eine Weile, ich dachte, das war die Funktion, die Timeout abzubrechen, aber das ist es nicht. Es ist die Funktion zum Abbrechen des Timeouts. – dshepherd

+0

@dshepherd bitte erklären, weil ich immer noch verwirrt bin. – natanavra

Verwandte Themen