iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 27
0
Modern Web

30天入門JavaScript系列 第 27

【Day 27】 setTimeout()跟非同步

出了點意外沒空寫了,壓底線


有時候會看到技術文寫JavaScript是同步(Synchronous)的,
代表JavaScript的程式會一行一行執行,一次只做一件事,目前的沒執行完不會作下一行程式

但真的是這樣嗎?先來看下面這個方法

setTimeout()

setTimeout()是個計時器,會在傳入的時間後回呼(callback)傳入的程式

像以下例子

setTimeout(() => {
  console.log('3秒過了');
}, 3000);

會在3000毫秒(3秒)後在控制台印出文字

setTimeout(() => {
  console.log('3秒過了');
}, 3000);

console.log('印出一些東西');

以同步的特性來看,JS應該會等三秒後印出3秒過了,再印出下面的印出一些東西

https://ithelp.ithome.com.tw/upload/images/20200927/20129836JzflWgpjpZ.png

但並沒有,打開瀏覽器後會發現瞬間印出印出一些東西,3秒過後才印出3秒過了
這跟說好的不一樣啊? 難道JavaScript可以一邊計時一邊執行下面的程式碼?

其實不是,JavaScript本身是同步的沒有錯,但執行他的瀏覽器是非同步的,
setTimeout()跟計時是瀏覽器提供的方法。

當使用setTimeout()時,要執行的函式跟時間會被傳給瀏覽器由瀏覽器來計時處理,
JS本身則會繼續執行下一行程式,等時間到了後瀏覽器在把函式傳回給JS執行。

那這種從外部傳回的任務是甚麼時候會執行?會立刻停止本來的程式立刻去執行嗎?

比如說像這樣

setTimeout(() => {
  console.log('3秒過了');
}, 0);

console.log('印出一些東西');

甚至這樣呢

setTimeout(() => {
  console.log('3秒過了');
}, 0);

var a = [];
for (let i = 0; i < 9999999999; i++) {
  a[i] = i;
  //不重要 反正就是一個要花好幾秒執行的程式碼
}
console.log('印出一些東西');

答案是3秒過了永遠會比印出一些東西晚印出

這些外部的事件在返回時不會直接給JS執行,而是進入一個叫做事件佇列(event queue)的地方,
以前提過JS是以呼叫堆疊來追蹤程式執行,當主程式執行完且呼叫堆疊為空時,
JS才會檢查事件佇列,把佇列內的任務放進呼叫堆疊來執行。

明日繼續


上一篇
【Day 26】ES6模組
下一篇
【Day 28】callback hell跟callback問題
系列文
30天入門JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言