Event Loop、 宏任務和微任務

本文將介紹我本身對JS Event Loop宏任務、微任務的理解。
二話不說先上圖:
promise

接下來將會針對此圖講解什麼是Event Loop 什麼事宏任務和微任務(其實聰明的大家經過圖大致也能瞭解的是吧~),再此以前先簡單介紹幾個概念。瀏覽器

爲什麼js是單線程

JavaScript的單線程,與它的用途有關。做爲瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操做DOM。這決定了它只能是單線程,不然會帶來很複雜的同步問題。好比,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另外一個線程刪除了這個節點,這時瀏覽器應該以哪一個線程爲準?異步

因此,爲了不復雜性,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特徵,未來也不會改變。函數

爲了利用多核CPU的計算能力,HTML5提出 Web Worker 標準,容許JavaScript腳本建立多個線程,可是子線程徹底受主線程控制,且不得操做DOM。因此,這個新標準並無改變JavaScript單線程的本質。(此段來自阮老師)oop

概念

  • 同步任務:在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務。
  • 異步任務:不進入主線程、而進入任務隊列(Task Queue)的任務。
  • 任務隊列:是一個事件的隊列(也能夠理解成消息的隊列),IO設備完成一項任務,就在"任務隊列"中添加一個事件,表示相關的異步任務能夠進入"執行棧"了。主線程讀取"任務隊列",就是讀取裏面有哪些事件。

詳解圖示

  1. 當一段代碼在主線程執行時,會有同步任務和異步任務,異步任務會判斷是微任務仍是宏任務,進行不一樣處理。而後繼續執行當前主線程內的代碼,直到結束。此段主線程執行的的爲宏任務
  2. 接着上面的判斷,宏任務的異步操做會先進入Event Table執行,而後當執行結束會把回調函數推入到Event Queue ,而後等待主線程的結束。對於微任務的異步會推入到另一個Event Queue ,等待主線程的結束。
  3. 當主線程結束後,先執行全部的微任務,而後執行把宏任務的任務隊列(Event Queue)中的event拉到主線程執行。
  4. 一直循環前面的操做。至此你應該懂的EventLoop了。
    備註:若是在執行 microtask(微任務) 的過程當中,又產生了microtask,那麼會加入到隊列的末尾,也會在這個週期被調用執行。

舉個例子🌰

setTimeout(function() {
    console.log('setTimeout');
}, 0)

new Promise(function(resolve) {
  console.log('promise 1');
  resolve();
  console.log('promise 2')
}).then(function() {
    console.log('promise then');
})

console.log('1');

輸出結果:promise 1 、promise 2 、1 、promise then 、setTimeout
解釋線程

  • 這段代碼做爲宏任務,進入主線程。
  • 先遇到setTimeout,則進入Event Table執行並註冊,而後將其回調函數發到宏任務Event Queue。
  • 接下來遇到了Promise,new Promise當即執行,then函數分發到微任務Event Queue。裏面的console.log(),當即執行。
  • 繼續,遇到console.log(),當即執行。
  • 至此這個主線程的宏任務執行結束,接着查找微任務,發現then的回調而後執行。
  • 第一輪事件循環結束了,咱們開始第二輪循環,從宏任務Event Queue開始執行。即宏任務Event Queue中setTimeout對應的回調函數,當即執行。
  • END。

爲什麼會有宏任務和微任務的說法。

eventloop中處理微任務和宏任務的邏輯也是不一樣廠商按照規範實現的 jsvm。code

補充幾個宏任務和微任務

宏任務 瀏覽器 Node
setTimeout
setInterval
setImmediate x
requestAnimationFrame x
微任務 瀏覽器 Node
process.nextTick x
MutationObserver x
Promise.then catch finally

來自個人簡書的文章:Event Loop、 宏任務和微任務server

相關文章
相關標籤/搜索