事件循環進階:macrotask與microtask

這段參考了參考來源中的第2篇文章(英文版的),(加了下本身的理解從新描述了下),前端

這裏無法給你們演示代碼,我就簡單說下個人理解吧。node

 

promise和settimeout 在一塊兒的時候執行順序是個有意思的事兒,promise

 

爲何呢?由於Promise裏有了一個一個新的概念:microtask瀏覽器

或者,進一步,JS中分爲兩種任務類型:macrotaskmicrotask,在ECMAScript中,microtask稱爲jobs,macrotask可稱爲task微信

 

它們的定義?區別?簡單點能夠按以下理解:多線程

  • macrotask(又稱之爲宏任務),能夠理解是每次執行棧執行的代碼就是一個宏任務(包括每次從事件隊列中獲取一個事件回調並放到執行棧中執行)學習

    • 每個task會從頭至尾將這個任務執行完畢,不會執行其它線程

    • 瀏覽器爲了可以使得JS內部task與DOM任務可以有序的執行,會在一個task執行結束後,在下一個 task 執行開始前,對頁面進行從新渲染
      code

(`task->渲染->task->...`)

 

  • microtask(又稱爲微任務),能夠理解是在當前 task 執行結束後當即執行的任務隊列

    • 也就是說,在當前task任務後,下一個task以前,在渲染以前

    • 因此它的響應速度相比setTimeout(setTimeout是task)會更快,由於無需等渲染

    • 也就是說,在某一個macrotask執行完後,就會將在它執行期間產生的全部microtask都執行完畢(在渲染前)

 

分別很麼樣的場景會造成macrotask和microtask呢?

  • macrotask:主代碼塊,setTimeout,setInterval等(能夠看到,事件隊列中的每個事件都是一個macrotask)

  • microtask:Promise,process.nextTick等

__補充:在node環境下,process.nextTick的優先級高於Promise__,也就是能夠簡單理解爲:在宏任務結束後會先執行微任務隊列中的nextTickQueue部分,而後纔會執行微任務中的Promise部分。

 

再根據線程來理解下:

    • macrotask中的事件都是放在一個事件隊列中的,而這個隊列由事件觸發線程維護

    • microtask中的全部微任務都是添加到微任務隊列(Job Queues)中,等待當前macrotask執行完畢後執行,而這個隊列由JS引擎線程維護(這點由本身理解+推測得出,由於它是在主線程下無縫執行的)

 

因此,總結下運行機制:

    • 執行一個宏任務(棧中沒有就從事件隊列中獲取)

    • 執行過程當中若是遇到微任務,就將它添加到微任務的任務隊列中

    • 宏任務執行完畢後,當即執行當前微任務隊列中的全部微任務(依次執行)

    • 當前宏任務執行完畢,開始檢查渲染,而後GUI線程接管渲染

    • 渲染完畢後,JS線程繼續接管,開始下一個宏任務(從事件隊列中獲取)

  • 另外,請注意下Promisepolyfill與官方版本的區別:

    • 官方版本中,是標準的microtask形式

    • polyfill,通常都是經過setTimeout模擬的,因此是macrotask形式

    • 請特別注意這兩點區別

    注意,有一些瀏覽器執行結果不同(由於它們可能把microtask當成macrotask來執行了),
    可是爲了簡單,這裏不描述一些不標準的瀏覽器下的場景(但記住,有些瀏覽器可能並不標準)

 

好了,到這裏我們這個從瀏覽器到多進程到多線程到js單線程到js運行機制就講完了。內容還算是比較全面,不足的就是隻能聽麼有代碼參考。

不過不要緊,你們能夠根據我提到的知識點本身再進行深刻的學習,或者關注下我我的的公衆號-重度前端,我講的內容都有文字版在上面並且有代碼,另外我記錄了一些我平時看到的比較好的 有深度的文章,還有一些原創內容。直接微信 搜 重度前端。 

 

好了,今天就到這裏了。後面計劃下分享哪些有意思的東西,我們下次見。

相關文章
相關標籤/搜索