Event Loop小計

我們都知道JavaScript是單線程的,也就是說同一時間只能幹一件事。這是因爲JavaScript主要是用來操作DOM的,如果變成多線程,瀏覽器就懵逼了,不知道該聽誰的了。但是雖然js是單線程,但是完全可以模擬多線程,靠的就是Event Loop

我們都知道js中的代碼分 同步異步,所謂的 異步 其實就是不會阻塞我們的主線程,等待主線程的代碼執行完畢纔會執行。callback setTimeout setInterval Promise ... 這些都是都是我們耳熟能詳的 異步 代碼


 

 

 

如圖所示,js中的內存分爲 堆內存(heap)棧內存(stack), 堆內存 中存的是我們聲明的object類型的數據,棧內存 中存的是 基本數據類型 以及 函數執行時的運行空間。我們的 同步 代碼就放在 執行棧 中,那異步代碼呢?瀏覽器會將 dom事件 ajax setTimeout等異步代碼放到隊列中,等待執行棧中的代碼都執行完畢,纔會執行隊列中的代碼,是不是有點像發佈訂閱模式。


console.log(1);
setTimeout(() => {
    console.log(2);    
}, 0);
console.log(3);
複製代碼

根據之前說的,setTimeout 會被放到隊列中,等待執行棧中的代碼執行完畢纔會執行,所以會輸出1, 3, 2


但是異步代碼也是有區別的:

console.log(1)

setTimeout(() => {
    console.log(2)
}, 0)

Promise.resolve().then(() => {
    console.log(3)
})
複製代碼

輸出的永遠是1, 3, 2, 也就是說 promisesetTimeout 之前執行了。這是因爲 異步任務 分爲 微任務(microtask)宏任務(task),執行的順序是 執行棧中的代碼 => 微任務 => 宏任務


執行棧

  • 執行棧中的代碼永遠最先執行

微任務(microtask): promise MutationObserver...

  • 執行棧中的代碼執行完畢,會在執行宏任務隊列之前先看看微任務隊列中有沒有任務,如果有會先將微任務隊列中的任務清空纔會去執行宏任務隊列

宏任務(task): setTimeout setInterval setImmediate(IE專用) messageChannel...

  • 等待執行棧微任務隊列都執行完畢纔會執行,並且在執行完每一個宏任務之後,會去看看微任務隊列有沒有新添加的任務,如果有,會先將微任務隊列中的任務清空,纔會繼續執行下一個宏任務

setTimeout(() => {
    console.log('timeout1')
    Promise.resolve().then(() => {
        console.log('promise1')
    })
    Promise.resolve().then(() => {
        console.log('promise2')
    })
}, 100)

setTimeout(() => {
    console.log('timeout2')
    Promise.resolve().then(() => {
        console.log('promise3')
    })
}, 200)
複製代碼
  1. 先將兩個setTimeout塞到宏任務隊列中
  2. 當第一個setTimeout1時間到了執行的時候,首先打印timeout1,然後在微任務隊列中塞入promise1promise2
  3. 當第一個setTimeout1執行完畢後,會去微任務隊列檢查是不是空的,他發現了有兩個promise,會把兩個promise按順序執行完再去執行下一個宏任務
  4. 兩個promise執行完畢後會微任務隊列中沒有任務了,會去宏任務中執行下一個任務 setTimeout2
  5. setTimeout2 執行的時候,先打印一個timeout2,然後又在微任務隊列中塞了一個promise2
  6. setTimeout2執行完畢後會去微任務隊列檢查,發現有一個promise2,會將promise2執行
  7. 會依次打印 timeout1 promise1 promise2 timeout2 promise3


作者:asdff
鏈接:https://juejin.im/post/5b63b4cb6fb9a04fb4017f5a
來源:掘金
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章