我每隔2秒轮询一次我的数据,以便在页面上更新它们。我的问题是当我访问另一个页面时,超时保持活动状态。当我访问新页面时,如何取消暂停?
function IndexCtrl($scope, $timeout, RestData) {
$scope.rd = {};
(function getRestDataFromServer() {
RestData.query(function(data){
$scope.rd = data;
$timeout(getRestDataFromServer, 2000);
});
})();
}
// EDIT 我找到了一个解决方案,但我不确定它是否是一个好的解决方案。当我将超时保存到$ 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);
}
答案 0 :(得分:64)
在更改路线时,有几个Angular事件正在广播。您可以使用IndexCtrl
在$scope.$on
内收听,并采取相应措施:
$ destroy event
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()
函数以取消超时。
答案 1 :(得分: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
。然后,例如,进行更新&#34;每30秒运行一次,直到$scope
被销毁:
update();
function update() {
// do the actual updating here
miscUtils.setTimeout($scope, update, 30000);
}
编辑让那些对deregister
发生了什么感到困惑的人:
此函数为$destroy
事件注册一个侦听器,但是一旦超时完成,就不再需要了;不再有超时取消。 scope.$on
返回一个函数,在调用时,取消注册该侦听器。因此,promise.then(deregister)
会在超时完成后立即清除不再需要的侦听器。