AngularJS取消超时

Posted

技术标签:

【中文标题】AngularJS取消超时【英文标题】:AngularJS cancelling a timeout 【发布时间】:2017-10-06 06:22:40 【问题描述】:

我有一个使用 AngularJS 和 Onsen/Monaca UI 开发的跨平台应用程序。

我有一个功能可以监视按钮点击的变化,如果在按钮上检测到一定数量的点击,用户会被带到一个确认屏幕。

但是,如果用户选择按钮的时间过长,则应将它们重定向到另一个屏幕(尚未定义)。

我正在尝试使用此功能实现 $timeout 功能,但一旦用户选择了正确次数的按钮,我似乎无法取消 $timeout。如果用户在允许的时间内选择了按钮,他们将被带到确认页面,但在 10 秒后仍然显示 $timeout 消息。

以下是我的实现。可以假设一切正常 - 除了 stop() 函数中的 $timeout.cancel()。

// Initialise
var timer;

// Watch for changes on button clicks
$scope.$watch('currentAction', function(newValue, oldValue) 
    if (counter == 6) 
        // User clicked buttons - cancel the timer
        stop();
        // Segue to next page
        Segue.goTo("confirmation.html");
    
    else 
        // Start the timer
        timer = $timeout(function () 
            alert("You are taking too long to respond");
        , 10000);
    
);

// Cancel the $timeout
function stop() 
    $timeout.cancel(timer);

Segue.goTo() 只是将用户转到传入的页面(无关,但为了清楚起见包括在内)

var myFunctions = 
    goTo: function (url) 
        var nextPage = url;
        var element = document.querySelector("ons-navigator");
        var scope = angular.element(element).scope();
        scope.myNavigator.pushPage(nextPage);
    ,

【问题讨论】:

你确认函数stop曾经被执行过吗? 是的,stop() 函数肯定被执行了。 请同时确认timer 不会在stop 之后重新创建。 据我所知不是,它似乎没有通过代码重新创建。 【参考方案1】:

你在$scope.$watch中创建timer,如果timer被多次创建并且只保留一个变量,你只能通过$timeout(timer)取消最新的一个。所以解决方案应该将$timeout 部分移出$scope.$watch 或将计时器保留在数组中并循环数组以停止它们。

如果您仍然坚持使用$scope.$watch,您应该在创建新之前取消之前的。

if (timer) 
    $timeout.cancel(timer);

timer = $timeout(function () 
    alert("You are taking too long to respond");
, 10000);

参考下面的代码sn-p。

timer 是在角端渲染页面后创建的。 timer 将在 test 更改后创建。

angular.module("app", [])
  .controller("myCtrl", function($scope, $timeout) 
    var timer;
    $scope.$watch('test', function(newValue, oldValue) 
      console.log('$timeout created. value:' + newValue);
      timer = $timeout(function() 
        console.log('$timeout fired. value:' + newValue);
      , 5000);
    )
    
    $scope.clickEvt = function() 
      console.log('$timeout canceld. currentValue:' + $scope.test);
      $timeout.cancel(timer);
    
  )
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
  <input type="text" ng-model="test">
  <button ng-click="clickEvt()">Stop<button>
</div>

【讨论】:

【参考方案2】:

尝试使用这个

$timeout.cancel(timer);

但你需要在 if 之前定义计时器

【讨论】:

之前试过了,还是没有取消$timeout。无论如何,$timeut 消息仍然显示。 @heyred 您正在初始化所有其他点击的超时。它尚未取消。唯一取消的超时是您最后创建的那个。所以您必须明确取消其他超时。我认为在 else 子句开头取消超时可以解决问题。 你能确定if状态下的定时器对象和else状态下的定时器对象是一样的吗?如果是这样,请将计时器作为参数传递给函数停止

以上是关于AngularJS取消超时的主要内容,如果未能解决你的问题,请参考以下文章

在 angularjs 中为 promise 设置超时处理程序

AngularJS $http 服务请求的默认超时是多少?

如何在 AngularJS 中取消 $http 请求?

自定义 X-editable (AngularJS) 的取消代码按钮

使用 Jasmine 对包含私有超时的单元测试 Angularjs 指令

AngularJs。是不是可以通过单击取消选择 HTML“收音机”输入?