說事件循環(event loop)之前先要搞清楚幾個問題。
- JavaScript引擎線程,用於解析JavaScript代碼
- GUI渲染線程,(它與javaScript線程是互斥的)
- 事件線程(onclick,onchange,…)
- 定時器線程(setTimeout, setInterval)
- 異步http線程(ajax),負責數據請求
- EventLoop輪詢處理線程,事件被觸發時該線程會把事件添加到待處理隊列的隊尾
- javaScript 中的任務可以被划分為宏任務(Macrotask)或者微任務(Microtask)。
- 像鼠標事件,鍵盤事件,"ajax","setTimeout"等就屬於宏任務,需要注意的是,主線程的整體代碼(script標簽),也是一個宏任務
- process.nextTick,PromiseA.then(), MutaionObserver 就屬於微任務

console.log(1); setTimeout(function(){ console.log(2) },10); new Promise(function(resolve){ console.log(3) for( var i=100000 ; i>0 ; i-- ){ i==1 && resolve() } console.log(4) }).then(function(){ console.log(5) }).then(function(){
console.log(6)
}) console.log(7);
打印出來的結果是:1 3 4 7 5 6 2
我們分析一下整個過程
1. 首先執行主線程這個宏任務,從上到下執行,遇到console.log(1); 打印1出來
2. 遇到setTimeout,把它丟給定時器線程處理,然后繼續往下執行,並不會阻塞10毫秒,而此處定時器線程會在,主線程執行完后的10毫秒,把回調函數放入宏任務隊列。
3. 遇到new Promise,直接執行,先打印 ‘3‘ 出來,然后執行for循環,達到條件之后,把promise的狀態改為resolved,繼續執行打印 ‘4’ 出來
4.遇到promise的then, 屬於微任務,則把回調函數放入微任務隊列
5.又遇到promise的then, 屬於微任務,則把回調函數放入微任務隊列
6. 遇到console.log(7) 打印 ‘7’ 出來
7. 宏任務執行完后會執行所有待執行的微任務,所以會相繼打印 ‘6’, ‘7’ 出來。
至此第一輪循環已經結束了,第一輪循環里的宏任務和微任務都會被移除出任務隊列,接下來開啟第二輪循環,
1.首先查找是否有宏任務,由於setTimeout 的回調被放入了宏任務隊列,這里會執行回調函數的代碼,打印了 ‘2’ 出來
2. 接着查找是否有微任務,發現沒有微任務,則本輪循環結束
接下來會重復上面的步驟,這就是event loop 了。后續當我們觸發點擊事件,有回調函數的話,回調函數也會被放入宏任務隊列,一旦隊列里重新有了任務,就會被執行。
6. 擴展題目
如果能把上面這道題的流程說清楚,那么恭喜你,對event loop理解的不錯了。 下面我們再利用上面的題目擴展一下,加深理解。
下面的代碼打印出來的結果是什么?
console.log(1); setTimeout(function(){ new Promise(function(resolve){ console.log('promise in setTimeout1'); resolve(); }).then(function(){ console.log('then in setTimeout1'); }) },10); new Promise(function(resolve){ console.log(3); for( var i=100000 ; i>0 ; i-- ){ i==1 && resolve(); } console.log(4) }).then(function(){ console.log(5); }); setTimeout(function(){ console.log('setTimeout2'); },10); console.log(7);
結果如下:
可以發現,第二個setTimeout 的回調函數,執行的比第一個setTimeout里面的promise.then()的回調要晚,這是因為每次循環只執行一個宏任務,但是卻會執行所有待執行的微任務,而第二個setTimeout在宏任務隊列的位置在第一個setTimeout后面。
這個就是我理解的JavaScipt 事件循環機制,參考了很多文章,也自己做了很多思考寫出來的,碼字不易,覺得有幫助可以點個贊哦。也歡迎留言交流
參考文章
https://segmentfault.com/a/1190000012806637?utm_source=tag-newest
http://www.ruanyifeng.com/blog/2014/10/event-loop.html
https://zhuanlan.zhihu.com/p/33127885
https://zhuanlan.zhihu.com/p/33136054
https://stackoverflow.com/questions/25915634/difference-between-microtask-and-macrotask-within-an-event-loop-context