启动新控制器时停止$ timeout

时间:2013-06-16 09:24:20

标签: angularjs angularjs-service

我每隔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); 
}

2 个答案:

答案 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)会在超时完成后立即清除不再需要的侦听器。