【问题标题】:Stop $timeout when starting new controller启动新控制器时停止 $timeout
【发布时间】:2013-06-12 11:30:24
【问题描述】:

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

【问题讨论】:

  • 你试过$timeout.cancel()吗?

标签: angularjs angularjs-service


【解决方案1】:

当路由改变时,有几个 Angular 事件被广播。您可以使用$scope.$onIndexCtrl 中收听它们并采取相应措施:

$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() 返回一个承诺对象。可以将此对象提供给$timeout.cancel() 函数以取消超时。

【讨论】:

  • 谢谢!这正是我一直在寻找的。 =)
  • 其实就是$timeout.cancel(promise)。
【解决方案2】:

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。然后,例如,创建一个每 30 秒运行一次的“更新”函数,直到 $scope 被销毁:

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

编辑对于那些对deregister 发生了什么感到困惑的人:

这个函数为$destroy事件注册了一个监听器,但是一旦超时完成就不再需要了;不再有取消的超时时间。 scope.$on 返回一个函数,该函数在调用时会取消注册该侦听器。因此,promise.then(deregister) 会在超时完成后立即清理不再需要的侦听器。

【讨论】:

  • 这听起来是一个很好的解决方案。您能否分享所有代码,例如一个工作示例,包括服务定义,所以对于我作为初学者来说,将它集成到我自己的应用程序中会更容易吗?谢谢!
  • deregister 变量让我困惑了一会儿,我以为是取消超时的功能,但事实并非如此。就是取消取消超时的功能。
  • @dshepherd 请解释一下,因为我仍然很困惑。
  • 如果变量被命名为deregisterDestroyListener 可能有帮助?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多