JavaScript中線程運行機制詳解

JavaScript中線程運行機制詳解

對於JavaScript咱們都知道,他是個單線程語言,可是準確來講它是擁有一個執行程序主線程,和消息隊列輔線程(Event Loop),以及各個真正處理異步操做的工做線程
當主線程執行JS程序的時候,若是遇到了異步的操做(如:click事件,setTimeOut,I/0操做,異步請求,Promise等),主線程將各個異步任務交給工做線程,主線程繼續執行,工做線程會判斷是否到了要執行該異步操做的條件了,若是工做線程判斷已經到了要執行工做線程的條件以後,就會把回調函數放入輔線程Event Loopmacrotask任務隊列或者microtask任務隊列的隊尾。當上述主線程執行完後續同步調用的代碼以後,輔線程會一直循環上面兩個隊列,首先執行的是microtask任務隊列,並且該任務隊列是該次循環就會執行完並清空的,macrotask會等到下次event loop循環的時候執行。web

Examplepromise

1.  console.log(1);
2.  setTimeout(function timerCallback(){
3.    console.log(2);
4.  },0)
5.  new Promise(function execute(resolve,reject){
6.     console.log(3);
7.     if(true)
8.         resolve();
9.  }).then(function resolveCallback(){
10.     console.log(4);
11. });
12. console.log(5);
// 上面程序執行的順序是:1,3,5,4,2

代碼詳解:當主線程執行上述代碼的時候,從上往下執行
一、先將console.log(1)這句代碼作一個入棧執行的操做,打印出1,該句代碼沒有後續的方法調用了,就出棧銷燬異步

二、執行setTimeout,將改句代碼入棧執行,判斷到該方法屬於WebAPIs(JS工做線程提供API的統稱,其中包含了webcore工做模塊提供了DOM Binding、network、timer等),timerCallback方法出棧,交給工做線程webcore下的timer模塊,這裏timer模塊會判斷是否到了執行條件了,因爲是延時是0,因此timer模塊判斷能夠執行了,並將回調函數timerCallback放到輔助線程Event Loop的macrotask隊尾,等待下一次Event Loop循環去執行。函數

三、繼續執行Promise這句代碼(包括then語句),將其入棧執行,判斷該Promise屬於Promise模塊(非WebAPIs),將其then的回調函數交給Promise模塊,有後續調用;將execute方法入棧執行,有後續調用;將console.log(3)入棧執行,打印出3,console.log(3)執行完畢,出棧銷燬;有後續調用if(true)入棧執行,判斷爲true,出棧銷燬,繼續將resolve()入棧執行,判斷resolve()是WebAPIs的成功的回調,執行的時候通知到上面的Promise模塊,Promise模塊將成功的回調放到Event Loop的microtask隊尾,resolve()出棧銷燬,無後續調用,Promise出棧銷燬。oop

四、繼續執行,將console.log(5)入棧執行,打印出5,無後續調用,出棧銷燬。線程

五、Event Loop開始循環microtask隊列,將resolveCallback()入棧執行,有後續調用;將console.log(4)入棧執行,打印出4,出棧銷燬;無後續調用,resolveCallback()出棧銷燬,清空隊列。code

六、Event Loop開始循環macrotask隊列,將timerCallback()入棧執行,有後續調用;將console.log(2)入棧執行,打印出2,出棧銷燬,無後續調用;將timerCallback()出棧銷燬,清空隊列。server

備註:

macrotask任務隊列的來源有:隊列

  • setTimeout事件

  • setInterval

  • setImmediate

  • I/O

  • UI rendering

microtask任務隊列的來源有:

  • process.nextTick

  • promises

  • Object.observe

  • MutationObserver

相關文章
相關標籤/搜索