事件輪詢概念
? 事件輪詢(Event Loop)是一個很重要的概念,指的是計算機系統(tǒng)的一種運行機制。JavaScript語言就是采用的這種機制,來解決單線程運行帶來的一些問題。
想要理解EventLoop,就要從程序的運行模式講起。運行以后的程序叫做"進程"(process),一般情況下,一個進程一次只能執(zhí)行一個任務(wù)。
如果有很多任務(wù)需要執(zhí)行,不外乎三種解決方法。
(1)排隊。因為一個進程一次只能執(zhí)行一個任務(wù),只好等前面的任務(wù)執(zhí)行完了,再執(zhí)行后面的任務(wù)。
(2)新建進程。使用fork命令,為每個任務(wù)新建一個進程。
(3)新建線程。因為進程太耗費資源,所以如今的程序往往允許一個進程包含多個線程,由線程去完成任務(wù)。
?以JavaScript語言為例,它是一種單線程語言,所有任務(wù)都在一個線程下完成,即采用上面的第一種方法,一旦遇到大量任務(wù)或者遇到一個耗時的任務(wù),網(wǎng)頁就會出現(xiàn)假死的狀態(tài),因為JavaScript停不下來,也就無法響應(yīng)用戶的行為。
很多人問為什么JavaScript不能實現(xiàn)多線程呢,例如如果是多線程的話,多個線程去操作同一個Dom元素,那么結(jié)果就造成一個很嚴重的問題,所以js是單線程的,但如果完全由上至下的執(zhí)行代碼,前面的代碼沒有執(zhí)行完,后面必須要等待當前執(zhí)行完畢,這樣的效率是非常低的,所以有了異步的概念,JavaScript 的主線程是單線程的,但是也有其他的線程去幫我們實現(xiàn)異步操作,比如Ajax 線程、定時器線程、事件線程。
JavaScript的任務(wù)
1.宏任務(wù)
宏任務(wù)包括整體代碼script,setTimeout,setInterval, I/O,UI Rendering
2.微任務(wù)
微任務(wù)包括Promise.then(非new Promise),process.nextTick
不同類型的任務(wù)會進入不同的Event Queue,有宏任務(wù)的隊列和微任務(wù)的隊列。
我們來看下面這道題就可以清晰了解宏、微任務(wù)區(qū)別:
setTimeout(() => { console.log( 'd' ); }, 0);
new Promise(resolve=>{
console.log('a');?
for(let i =0;i<10000;i++){ i == 9999 && resolve(); } console.log( 'b' ) }).then(()=>{ console.log( 'e' ) })??
?console.log( 'c' )?
答案是 a b c e d,讓我們來看看執(zhí)行流程:

通過圖片我們可以看出,進入整體代碼(宏任務(wù))后,開始第一次循環(huán)。接著執(zhí)行所有的微任務(wù)。然后再次從宏任務(wù)開始,找到其中一個任務(wù)隊列執(zhí)行完畢,再執(zhí)行所有的微任務(wù)
所以上面那道題是宏任務(wù)會先將延時器放到事件隊列中,等待下一輪執(zhí)行宏任務(wù)才會執(zhí)行延時器,繼續(xù)找宏任務(wù)a b c ,直到?jīng)]有宏任務(wù)就會執(zhí)行微任務(wù),也就是e ,微任務(wù)也執(zhí)行完畢,就會開啟新一輪的執(zhí)行宏任務(wù),所以最后打印d