繁体   English   中英

无限循环,而没有明显的原因

[英]Infinite loop in while for no aparent reason

我正在研究一个计时器,经过我在这个论坛得到的一些答案后,它一直在顺利进行。 这就是它现在的样子:(只是为了让你明白这一点)

在此输入图像描述

我的代码(请注意,这是一项正在进行的工作,所以有些东西还没有完成;基本上每个有alert("workin");功能alert("workin");仍然没有被使用。

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <!DOCTYPE html> <html> <head> <title>WIP</title> <meta charset="UFT-8"> <link rel="stylesheet" href="style.css"> <script src="script.js"></script> <script> $(document).ready(function() { timerSet(9,12); timerRun(); }); function timerReset() { alert("workin"); } function timerSet(inputMinutes, inputSeconds) { minutes = inputMinutes; seconds = inputSeconds; finalTimeInSeconds = minutes*60 + seconds; //finalTimeInSeconds is the time it takes for the timer to be 00:00 in seconds. timerPrint(); } function timerAdd(inputMinutes, inputSeconds) { alert("workin"); } function timerSubtract(inputMinutes, inputSeconds) { setTimeout(function () { if(minutes > 0 && seconds == 0) { minutes--; seconds = 59; } else { seconds--; } timerPrint(); }, 1000); } function timerRun() { timerSubtract(); } function timerStop() { alert("workin"); } function timerPrint() { displayMinutes = (minutes.toString().length == 2) ? minutes : "0" + minutes; //ternary operator: adds a zero to the beggining displaySeconds = (seconds.toString().length == 2) ? seconds : "0" + seconds; //of the number if it has only one caracter. $("#timerText").text(displayMinutes + ":" + displaySeconds); } function totalTime() { var totalTimeInSeconds = minutes*60 + seconds; return totalTimeInSeconds; //totalTimeInSeconds is the time that the timer now displays in seconds. } </script> </head> <body> <div id="timerText">00:00</div> </body> </html> 

所以这是我的问题:在timerRun()函数中,我想让timerSubtract()函数重复,而totalTime() > 0 ,但是如果我使用while循环,页面就会崩溃。 为什么这样做? 我不认为这是一个无限循环。 我该怎么做才能想要?

感谢无论谁回答! :-)

问题是timerSubtract使用setTimeout完成它的工作。

每次使用setTimeout您都可以想象它会暂时setTimeout该函数。 然后,一旦程序没有做任何事情(并且如果已经过了足够的时间),那么它将运行下一个被搁置的函数。 通过运行while循环,您永远不会让运行时有机会运行使用setTimeout预留的函数。

在仍使用setTimeout同时解决此问题的一种方法是执行以下操作:

function timerRun() {
    if (minutes > 0 && seconds == 0) {
        minutes--;
        seconds = 59;
    } else {
        seconds--;
    }
    timerPrint();
    // Queue up timerRun to run again in 1 second
    setTimeout(timerRun, 1000);
}
timerRun();

而不是使用setTimeout,为什么不使用setInterval:

http://jsfiddle.net/ouL1yzpq/

setInterval(function () {
    if(minutes > 0 && seconds == 0) {
        minutes--;
        seconds = 59;
    } else {
        seconds--;
    }
    timerPrint();
}, 1000);

检查一下,看看如何停止计时器: 如何停止“setInterval”

timerSubtract函数不会更改变量minutesseconds 它只会启动一个超时,以便稍后更改变量。

如果在循环中运行函数等待变量更改,那么变量将永远不会有任何更改。 JavaScript是单线程的,因此您必须退出该函数并将控件返回到浏览器以执行超时。 循环运行时,将不会处理超时事件。

如果JavaScript本来是多线程的,那么你的循环将启动数百万次超时,直到一秒钟过去并且超时将开始执行。 由于您没有每秒启动超时但速度尽可能快,因此计时器将立即倒数至数百万。

而不是启动大量超时,在timerSubtract使用单个setInterval ,并且只调用一次函数。 间隔将每秒倒计时一次,因为我怀疑你的计时器是如何工作的:

function timerSubtract(inputMinutes, inputSeconds) {
    setInterval(function () {
        if(minutes > 0 && seconds == 0) {
            minutes--;
            seconds = 59;
        } else {
            seconds--;
        }
        timerPrint();
    }, 1000);
}

function timerRun() {
    timerSubtract();
}

正如Jonathan发布的那样,您可以使用setInterval。 我会在他的答案中添加clearInterval()来停止0(这是你想要的吗?)像这样:

function timerSubtract(inputMinutes, inputSeconds) {
    var countdown = setInterval(function () {
        if(minutes > 0 && seconds == 0) {
            minutes--;
            seconds = 59;
        } else {
            seconds--;
        }

        if( totalTime() <= 0){
            clearInterval(countdown);
            // timer is done, do something interesting..
        }

        timerPrint();
    }, 1000);
}

此外,很长一段时间计时器可能不准确。 如果您想要更好的精度,请在启动计时器时读取实际当前系统时间,然后在每个时间间隔再次读取实际时间并减去两个值(当前 - 开始)以获得实际经过的时间。 然后从初始总计中减去经过的时间以获得剩余的当前时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM