js的Event Loop機制解析

概述

最近看了一些異步的文章,有一些做者沒有寫代碼也把錯誤的理解放上來。想一想,我也應該總結一些,以前面試也有過一道題目,雖說是考察異步,但其實就是考察異步當中的任務隊列。給你一道題目,你以爲會依次輸出什麼?git

console.log('1')

Promise.resolve().then(() => console.log('2'))

setTimeout(() => {console.log('3'); Promise.resolve().then(() => console.log('4'))}, 0)

Promise.resolve().then(() => console.log('5'))

setTimeout(() => console.log('6'), 0)

console.log('7')

答案是github

1 7 2 5 3 4 6

若是你知道爲何會輸出這些的話,那我想你沒必要看下面了,由於你也有大概的理解,若是沒有的話,我就跟你分析一下吧。面試

先看一張圖吧,是拿別人的,有部分緣由也是由於他寫的文章有錯誤,我才總結。segmentfault

image

先理解這張圖片吧,我簡單介紹一下。markdown

  • 棧:主線程的函數執行,異步操做的執行放在了異步處理模塊。
  • 堆:用來存儲引用類型的指向。
  • 異步處理模塊:主線程裏面的異步模塊。
  • 任務隊列:存儲異步線程的執行隊列。

而後,js運行就是運行主線程->運行任務隊列異步

固然,這只是大概的介紹,真正的堆和棧並非和他說的同樣,棧裏面還有內存棧和調用棧,內存棧又有全局的內存棧,也有某個函數的內存棧,固然,函數內部的內存棧又放在了堆裏面。這裏面的棧,僅僅是表明了調用棧。函數

宏任務隊列(macrotasks)

什麼是宏任務隊列?

宏任務隊列macrotasks: setTimeout, setInterval, setImmediate, I/O, UI renderingoop

上面的基本操做就是宏任務隊列spa

微任務隊列(microtasks)

微任務隊列microtasks: process.nextTick, Promise, MutationObserver線程

上面的基本操做就是微任務隊列

Event Loop

我就簡單的說一下js裏面執行順序吧:

  1. 執行主線程,若是有異步操做,則放到異步隊列執行。執行2
  2. 當主線程執行完畢,判斷異步隊列是否有微任務,若是有,則添加進去主線程執行;若是沒有則將最新能夠執行的宏任務加進主線程。返回1

是否是很簡單?
那麼上面那道題的結果無非就是

// 一開始,主線程
console.log('1');
console.log('7');

// 下一步,主線程
Promise.resolve().then(() => console.log('2'))

// 下一步,主線程
Promise.resolve().then(() => console.log('5'))

// 下一步,主線程
setTimeout(() => {console.log('3')}, 0)

// 下一步,主線程
Promise.resolve().then(() => console.log('4'))

// 下一步,主線程
setTimeout(() => console.log('6'), 0)

總結

看了一下不少文章,覺得很難,很想畫圖,可是在寫的過程當中,發現其實真的很簡單,只要好好了解js裏面的引擎就行了,js仍是一個很強大的單線程語言。

相關文章
相關標籤/搜索