理解 while 迴圈與 setTimeout 衝突:原因與解決方法

更新日期: 2024 年 11 月 14 日

在 JavaScript 中,我們有時會希望使用 while 迴圈來持續執行某個條件成立的操作,同時結合 setTimeout 方法進行定時處理。

然而,這兩者結合時,可能會出現程式碼無法正常執行的情況。

本文將分析這個衝突的原因,並提供解決方法。

問題描述:while 迴圈與 setTimeout 衝突

以下是一個代碼範例:

let statusDefaul = true;

function test() {
  while (statusDefaul) {
    setTimeout(() => {
      statusDefaul = false;
      console.log(statusDefaul);
    }, 1000);
  }
}

test();

在這段程式碼中,我們定義了一個 test 函數,包含一個 while 迴圈和一個 setTimeout 定時器。

while 迴圈中,setTimeout 被用來在 1 秒後將 statusDefaul 設為 false,並在控制台輸出。

理論上,while 迴圈應該在 statusDefaul 被設為 false 後停止。

但實際上,程式會陷入無窮迴圈,且不會輸出任何結果。

問題原因:事件迴圈阻塞

在 JavaScript 中,while 迴圈屬於同步操作,而 setTimeout 屬於異步操作。

當執行到 while 迴圈時,JavaScript 會持續檢查 statusDefaul 是否為 true

由於 while 迴圈是一個同步阻塞操作,它會持續執行而不會等待 setTimeout 的回呼函數執行。

因此,while 迴圈會讓程式陷入無窮迴圈,阻止 setTimeout 的回呼函數執行。

即使 setTimeout 設置了 1 秒的延遲,但在 while 迴圈結束之前,這個異步操作無法被執行,導致 statusDefaul 無法被設為 false,程式最終無法正常停止。

解決方法

要解決這個問題,可以使用以下方式來替代 while 迴圈:

解法:使用 setInterval

setInterval 可以用來在指定的時間間隔內,重複執行一段程式碼。

使用 setInterval,我們可以設定一個 1 秒的間隔來檢查並更新 statusDefaul,直到條件不再成立。

改寫範例

let statusDefaul = true;

const intervalId = setInterval(() => {
  if (statusDefaul) {
    statusDefaul = false;
    console.log(statusDefaul);
  } else {
    clearInterval(intervalId); // 停止 `setInterval`
  }
}, 1000);

在這段程式碼中,setInterval 每隔 1 秒檢查一次 statusDefaul 的值。

statusDefaultrue 時,它會將其設為 false 並輸出結果。

隨後,clearInterval 用來停止 setInterval,避免重複執行。

結論

在 JavaScript 中,while 迴圈和 setTimeout 的組合可能會因為同步和異步的衝突而導致程式無法正常執行。

透過使用 setInterval,我們可以在不阻塞程式執行的情況下實現相同的效果。

這不僅避免了程式碼阻塞問題,也提升了程式的穩定性和可讀性。

Similar Posts