27

ページ上でデータを更新し続けるために、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); 
}
4

2 に答える 2

65

ルートが変更されているときにブロードキャストされる 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()promise オブジェクトを返します。$timeout.cancel()このオブジェクトは、タイムアウトをキャンセルする機能に提供できます。

于 2013-06-17T07:54:02.467 に答える
15

Stewieの答えは完璧です。$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ました。次に、たとえば、$scopeが破棄されるまで 30 秒ごとに実行される「更新」関数を作成するには:

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

何が起こっているのか混乱している人のために編集deregisterしてください:

この関数は$destroyイベントのリスナーを登録しますが、タイムアウトが完了すると不要になります。キャンセルするためのタイムアウトはなくなりました。scope.$on呼び出されると、そのリスナーの登録を解除する関数を返します。そのpromise.then(deregister)ため、タイムアウトが完了するとすぐに、不要になったリスナーをクリーンアップします。

于 2014-06-13T19:28:06.637 に答える