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);
}
ルートが変更されているときにブロードキャストされているAngularイベントがいくつかあります。_$scope.$on
_を使用してIndexCtrl
内でそれらをリッスンし、それに応じてアクションを実行できます。
$ 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()
関数に提供して、タイムアウトをキャンセルできます。
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);
}
_
Editderegister
で何が起きているのか混乱している人のために:
この関数は_$destroy
_イベントのリスナーを登録しますが、タイムアウトが完了すると不要になります。キャンセルするタイムアウトはなくなりました。 _scope.$on
_ は、呼び出されたときにそのリスナーの登録を解除する関数を返します。そのため、promise.then(deregister)
は、タイムアウトが完了するとすぐに、不要になったリスナーをクリーンアップします。