簡體   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