1

我试图辩论这是否是在 Javascript 中处理计时器的好方法。我正在使用 Angular,但概念与使用setTimeout而不是$timeoutAngular 提供的功能相同。

老方法:

$scope.timer=$scope.doTiming();
$scope.timeRemaining=30; //30 second timer;
$scope.doTiming=function(){
    return $timeout(function(){
        $scope.timeRemaining=$scope.timeRemaining-1;
        if($scope.timeRemaining<=0){
            $scope.disabledEntry=true;
            $scope.submitData();
        }else{
            $scope.timer=$scope.doTiming();
        }
    },1000);
};

30 计时器经过的时间:30.050 seconds

新方法:

var startTime=new Date().getTime, delta; //new: get current time
$scope.timeRemaining=30;
$scope.timer=$scope.doTiming();
$scope.doTiming=function(){
    return $timeout(function(){
        delta=(new Date().getTime())-startTime; //new: get delta from start time
        $scope.timeRemaining=$scope.timeRemaining-(delta/1000); //new: subtract by delta
        if($scope.timeRemaining<=0){
            $scope.disabledEntry=true;
            $scope.submitData();
        }else{
            $scope.timer=$scope.doTiming();
        }
    },1);
};

30 计时器经过的时间:30.002 seconds

主要区别在于旧方式每秒循环一次,并关闭计时器。新方式不断循环非常快,并根据从一开始的时间变化来测量时间,因此它有可能更准确。我想知道这是否合理?这种类型的即时循环会在旧计算机上引起问题吗?我是否应该使用计时器为 100 而不是 1 的新方法?想法?

编辑

由于与超时减慢相关的原因,新方法对我来说更可取:Chrome:超时/间隔在后台选项卡中暂停?

4

1 回答 1

2

在我看来,你应该做尽可能多的“超时”,但尽可能少。换句话说,如果您需要每秒更新一个计时器,则每秒触发一次超时。没有人会注意到定时器更新的 50 毫秒延迟(也不会有人关心),所以我认为不值得用额外的 JavaScript 周期来打扰浏览器,例如。可能会更好地用于更新一些动画。

我想不出为什么这也不适用于增量时间方法。最坏的情况是标签在触发一秒超时后立即进入后台。当用户返回选项卡时,大约需要一秒钟时间才能刷新计时器,并且在该时间间隔内,用户仍然会看到他使选项卡处于非活动状态时的计时器值。如果这对您的用例是可以接受的,我根本不会担心增加间隔:)

于 2013-10-24T20:25:12.450 回答