JavaScript核心概念 - 執行續、同步與非同步:為何setTimeout不一定會在1秒後執行呢?

首先,我們要知道 JavaScript 是一個單執行緒 (single threaded) 的程式語言,一次只會執行一段程式碼,執行環境會形成執行堆疊,執行完畢才將堆疊抽離,但在所有非同步事件如 click、setTimeout、ajax…,不會執行這樣的行為。

故事說明

ASin 剛買回來一份鹹酥雞,但想到剛剛學的 code 還沒練習完,想了想還是先練完再來吃好了,所以 ASin 會做以下的動作:

  • 掙扎了一下還是去練習寫 code
  • 開始練習 coding
  • 終於吃到鹹酥雞
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Buyfood() {
var food = '鹹酥雞';

(function() {
console.log('先學習 code');
setTimeout(function() {
console.log('練習完可以吃' + food + '了');
}, 3000);
})();

(function() {
console.log('練習 coding');
})();
}

Buyfood(); // 執行

// 先學習 code
// 練習 coding
// 練習完了可以吃鹹酥雞了

Event queue

我們可以看到 ASin 很認真的學習,將美味的鹹酥雞先擱置在一旁,這被擱置在一旁的鹹酥雞等待著 ASin 來享用在 JavaScript 稱為 Event queue。由於 setTimeout 是非同步執行,當 setTimeout 執行後其 callback function 會從堆疊中拖離,送到 Event queue,等待條件達成,但是,當條件達成時,Event queue 內的 callback function 還是要等待原本的執行堆疊都執行完後,才會被觸發。我們可以將上面的 setTimeout 改成 0 再來試試看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Buyfood() {
var food = '鹹酥雞';

(function() {
console.log('先學習 code');
setTimeout(function() {
console.log('練習完可以吃' + food + '了');
}, 0);
})();

(function() {
console.log('練習 coding');
})();
}

Buyfood(); // 執行

// 先學習 code
// 練習 coding
// 練習完了可以吃鹹酥雞了

我們還是會得到了同樣的結果。所以,當我們在為 setTimeout 設定時間條件時,其並不一定會在設定好的時間後就去執行,還是要看原執行堆疊的執行情況。

0%