2014-10-10 94 views
0

我遇到了無法解決的問題。我在JavaScript中有一個循環,其中停止的條件變量取決於全局變量。循環開始循環,當我更改該全局變量的值時,它永遠不會停止。條件變量(全局變量)在javascript中更改時的停止循環

stop = false; 
var i = 0; 
while ((stop == false) && (i<100000)){ 
    console.log("hi-"+i); 
    i++; 
} 

while循環運行時,如果我停止= true,它永遠不會停止。我不知道那是爲什麼。

有什麼想法?

謝謝!

+0

您的代碼不會更改循環內的「stop」 – hindmost 2014-10-10 14:03:32

+0

JavaScript是單線程的。你的事件處理程序(我想)將'stop'設置爲'true'只會在while循環完成後執行。 – techfoobar 2014-10-10 14:03:42

+0

@最後我改變停止在循環外的值... – user2422900 2014-10-10 14:18:23

回答

2

JavaScript本質上是單線程的。一旦一段代碼開始運行,它會在發生任何事情之前運行完成。 IE設置stoptrue的事件只有在while循環結束後纔會執行。

您需要將循環分割成多個段和單獨運行各個部分,讓其他事件發生:

stop = false; 
var i = 0; 

function loopLogic() { 
    var tempStop = i + 500; 
    while (i < tempStop) { 
    //original processing logic 
    console.log("hi-" + i); 
    i++; 
    } 

    if (!stop && i < 100000) 
    window.setTimeout(loopLogic, 0); 

} 
window.setTimeout(loopLogic, 0); 

這同時打破了該功能分爲500多個塊。 0持續時間的setTimeout讓函數立即繼續(幾乎),但會將下一個塊放在執行鏈的底部。這允許發生其他事件,因此將允許更新stoptrue

Here's a fiddle顯示了這種方法。

在兼容的瀏覽器提供的另一種方法是Web Worker,但這種情況已經開始擺脫這一問題的範圍。

+0

感謝您的回答 – user2422900 2014-10-10 14:18:58

+0

我可以這樣做的方式是? 想象一下,idk,當我點擊身體時,我想要停下來......我怎麼能實現這樣的事情? – user2422900 2014-10-10 14:20:30

+0

我會編輯我的答案建立在@giordanolima暗示的方法... – 2014-10-10 14:22:21

0

您可以嘗試使用setInterval .... 把你需要做的到的功能,並在一定的時間間隔叫什麼... 採取這裏看看......

http://jsfiddle.net/o5mnb7jv/1/

var stop = false; 
var obj = document.getElementById("btn").addEventListener("click", function(){ 
    stop = true; 
}); 
var interval; 
function loop(){ 
    var result = document.getElementById("result"); 
    if(!stop){ 
     result.innerHTML = "Running..."; 
    }else{ 
     clearInterval(interval); 
     result.innerHTML = "Stopped..."; 
    } 
} 
interval = setInterval(loop, 500); 
+0

嗯......但我需要該功能執行有限的時間。使用setInterval將無限執行,直到停止更改。 – user2422900 2014-10-10 14:24:55

+0

您可以存儲間隔的實例並使用clearInterval來停止它.... – giordanolima 2014-10-10 14:32:40

0

這聽起來像你期待的JS是多線程的,但它不是,這使得某些事情真棒。例如,如果JS是多線程的,下面會做什麼?

if (x === 3) { 
    alert(x); 
} 

在JS的答案是「它警告3」,但如果JS是多線程的,就什麼也沒有從IF和警報之間的編輯X停止另一個線程,所以它不會被明確定義。

您可以控制權返回給瀏覽器的事件循環,同時確保一些代碼運行,通過調度該功能,無論是與setTimeoutsetInterval。如果您希望遞歸的結果是異步的,這也可以讓您在沒有大量調用堆棧的情況下執行遞歸。此外,JS正在獲得一項新功能(生成器和yield關鍵字),這將使它更容易「暫停」中間某個功能,以便稍後恢復。

做你想做什麼,最簡單的方法是:

var i = 0, running = true; 
function iter() { 
    if (running && i < 100000) { 
     console.log("hi", i++); 
     setTimeout(iter, 0); 
    } 
} 
iter(); 

您也可以在setTimeout調用使用一個非零時間 - 例如人類的反應時間大約是200毫秒,所以如果你只是需要它從人類的角度來看似乎是連續的,請將0更改爲100;它會給你的電腦多一點空間來呼吸。

你也可以使用setInterval,但要知道如果一些CPU密集型函數阻塞了其他一段時間的執行,你將排隊一堆相同的函數,它們都希望一個接一個地執行。當setTimeout線程調用setTimeout時,有一個最小延遲,它由setTimeout強制執行; setInterval並不是這種情況(它聲稱調用之間的平均時間是一致的,但沒有聲明它們之間的最小或最大延遲)。

爲了setInterval的緣故,您可能希望在某點之後停止間隔。在i上加上if檢查當然會使該函數成爲一個空功能,它什麼都不做,所以它不會浪費太多時間,但是如果你不想調度它,捕獲setInterval的結果並將它傳遞給clearInterval