为什么我的javascript倒计时器偶尔会超时?

时间:2014-01-31 19:09:36

标签: javascript recursion timer

作为基于网络的教育游戏的一部分,我有一个使用下面代码的倒数计时器。大多数情况下,计时器停在零,但偶尔会超时,并从59:59继续倒计时。

关于代码的几点说明:

  1. countTime是一个由下拉菜单设置的全局变量
  2. stopCount是由重置按钮设置的全局变量
  3. leadZero是用于格式化的外部函数
  4. 据我所知,setTimeout不是很准确,但我原以为remTime> 0条件最终会停止递归,即使它第一次错过了。

    无论如何,这是代码:

    function newCount() {
        var startTime=new Date();
        var min=startTime.getMinutes();
        var sec=startTime.getSeconds();
        var endTime=(min*60)+sec+countTime;
        stopCount=false;
    
        countDown();
    
        function countDown() {
            var today=new Date();
            var m=today.getMinutes();
            var s=today.getSeconds();
            var currTime=(m*60)+s;
            var remTime=endTime-currTime;
            var remMin = Math.floor(remTime/60);
            var remSec = remTime % 60;
    
            // add a zero in front of numbers<10
            remMin=leadZero(remMin);
            remSec=leadZero(remSec);
    
            document.getElementById('timer').innerHTML=remMin+":"+remSec;
    
            if (remTime > 0 && stopCount==false) { 
                t=setTimeout(function(){countDown()},500);
            }
            else if (stopCount==false){document.getElementById("nextButton").innerHTML = "Finished";}
            else {} 
        }   
    }
    

    根据要求,这里是按钮和调用函数的代码......

    按钮:

    <button onclick="newSyllable()" id="nextButton" style="font:60px 'Nunito', sans-serif;">Start</button>
    
    <button onclick="resetScore()"><span style="font:20px 'Nunito', sans-serif;">Reset</span></button>
    

    功能:

    function resetScore() {
        points=0
        stopCount=true;
        document.getElementById("score").innerHTML = "Score: " + points
        document.getElementById("nextButton").innerHTML = "Start"
        document.getElementById("syllable").innerHTML = "&nbsp;"
        t=setTimeout(function(){setCountDown()},500);
    }
    
        function newSyllable() {
        if (document.getElementById("nextButton").innerHTML == "Finished"){
        }
        else {
            if (document.getElementById("nextButton").innerHTML == "Start"){
                newCount();
            }
    
            document.getElementById("nextButton").innerHTML = "Next"
    
    
            switch (currentUnit) {
            case "1":
                unit1();
                break;
            case "2":
                unit2();
                break;
            case "3":
                unit3();
                break;
            case "4":
                unit4();
                break;
            case "5":
                unit5();
                break;
            case "6":
                unit6();
                break;
            }
            document.getElementById("score").innerHTML = "Score: " + points++
        }
    }
    

2 个答案:

答案 0 :(得分:1)

好的,我认为问题源于你使用两个Date对象计算剩余时间的方式。更简单的方法是使用countTime变量作为开始时间(以秒为单位),然后使用1000毫秒的间隔来执行倒计时。请尝试使用此代码:

var stopCount = false;
var countTime = 10;

function newCount() {
    if(stopCount === false) {
        var counter=setInterval(countDown, 1000);
    }
    stopCount = true;

    function countDown() {
        countTime = countTime - 1;
        var remMin = Math.floor(countTime/60);
        var remSec = countTime % 60;
        // add a zero in front of numbers<10
        remMin=leadZero(remMin);
        remSec=leadZero(remSec);
        document.getElementById('timer').innerHTML=remMin+":"+remSec;

        if (countTime <= 0)
        {
            clearInterval(counter);
            document.getElementById("nextButton").innerHTML = "Finished";
            return;
        }
    }   
}

JSFiddle:http://jsfiddle.net/5vxbe/8/

答案 1 :(得分:0)

我使用@JL中的countTime = countTime-1想法进一步简化了代码,但使用了我原来的setTimeout递归函数而不是setInterval和clearInterval。

我希望“重置”按钮能够在完成之前停止并重置计时器,而且这段代码使得它更简单(我认为)。

这是最终的代码:

function newCount() {
    stopCount=false;
    countDown();
    function countDown() {
        if (stopCount==false) {
            countTime=countTime-1
            var remMin = Math.floor(countTime/60);
            var remSec = countTime % 60;

            // add a zero in front of numbers<10
            remMin=leadZero(remMin);
            remSec=leadZero(remSec);
            document.getElementById('timer').innerHTML=remMin+":"+remSec;
            if (countTime > 0) { 
                t=setTimeout(function(){countDown()},1000);
            }
            else {document.getElementById("nextButton").innerHTML = "Finished";}
        }

    }   
}