1. 程式人生 > 其它 >事件迴圈、巨集任務、微任務

事件迴圈、巨集任務、微任務

*巨集任務*:在js中,在主執行緒上執行的任務叫巨集任務,常見的有:

  1. 1渲染事件
  2. 使用者互動事件
  3. js指令碼
  4. 網路請求、檔案讀寫完成事件
  5. 延遲事件(定時器)

普通任務佇列、延遲佇列中的任務都屬於巨集任務。

為了讓這些事件有條不紊的進行,js引擎需要對執行的順序做一定的安排,v8其實採用是一種佇列的方式來儲存這些任務,即先進來的先執行。

*微任務*:對於每個巨集任務而言,其內部都有一個微任務佇列,那為什麼要引入微任務?微任務在什麼時候執行?

引入微任務的初衷是為了解決非同步回撥問題,如果把非同步回撥放在巨集任務,會造成卡頓。為了解決這一問題,v8引入微任務,在每一個巨集任務中定義一個微任務佇列,當該巨集任務執行完成,會檢查其中的微任務佇列,如果為空則執行下一個巨集任務,如果不為空,則依次執行微任務,執行完成採取執行下一個巨集任務。常見的微任務有:

  1. MutationObserver
  2. Promise.then(或.reject)以及以Promise為基礎開發的其他技術(比如fetch API)
  3. v8垃圾回收機制
  4. nextTick

事件迴圈--js執行機制(eventLoop)

例子:

console.log('start');
setTimeout(() => { console.log('timeout');});
Promise.resolve().then(() => { console.log('resolve');});
console.log('end');

分析一下:

1)剛開始整個指令碼作為一個巨集任務來執行,因此先列印start和end

2)setTimeout 作為一個巨集任務放入巨集任務佇列

3)Promise.then作為一個為微任務放入到微任務佇列

4)當本次巨集任務執行完,檢查微任務佇列,發現一個Promise.then, 執行5)接下來進入到下一個巨集任務——setTimeout, 執行

start
end
resolve
timeout

1)一開始整段指令碼作為第一個巨集任務執行

2)執行過程中同步程式碼直接執行,巨集任務進入巨集任務佇列,微任務進入微任務佇列

3)當前巨集任務執行完出隊,檢查微任務佇列,如果有則依次執行,直到微任務佇列為空

4)執行瀏覽器 UI 執行緒的渲染工作

5)檢查是否有Web worker任務,有則執行

6)執行隊首新的巨集任務,回到2,依此迴圈,直到巨集任務和微任務佇列都為空

// 練習
Promise.resolve().then(()=>{ console.log('Promise1')  	     setTimeout(()=>{  console.log('setTimeout2') },0)});
setTimeout(()=>{ console.log('setTimeout1')            		Promise.resolve().then(()=>{  console.log('Promise2')   })},0);
console.log('start');
// start// Promise1// setTimeout1// Promise2// setTimeout2