基于真實案例淺談事件循環(huán)EventLoop
前情提要
為什么說是淺談呢?因為EventLoop的牽扯到的情況特別復雜也特別的龐大,一句兩句講不清楚,可能講著講著把自己就給講糊涂了。所以我們就由表及里,以結(jié)果為導向看看事件循環(huán)的運行機制。
什么是事件循環(huán)?
事件循環(huán)的本質(zhì)是在瀏覽器或者nodejs的環(huán)境中,運行時對js腳本的調(diào)度方式。
首先我們先了解下js為什么會有事件循環(huán)機制?
我們都知道JavaScript是單線程的。所謂單線程,就可以理解為一個人的心一段時間只能放下一個人,分開了才能去存放另一個人,無法一心二用。但是如果按照這種情況走下去,假如代碼塊中遇到了計時器5秒甚至50秒后觸發(fā),那么整個程序都會因為還沒有到程序的執(zhí)行時間而停滯不前,進而進入假死狀態(tài)。這種情況自然是我們所不希望看到的,我們希望遇到此類需要等待的代碼時跳過去,先執(zhí)行不需要等待的代碼,最后再來執(zhí)行這些需要等待的代碼。于是JavaScript就引入了事件循環(huán)機制,來模擬多線程的效果。
而實現(xiàn)這種效果的方式就是事件循環(huán)EventLoop機制
其次是如何實現(xiàn)這種機制
同步任務(wù)為一個任務(wù)執(zhí)行棧(棧的規(guī)則是先進后出)
異步任務(wù)是一個消息隊列(消息隊列的規(guī)則是先進先出)。
同時還有瀏覽器提供的webApi,可以理解為瀏覽器自己提供的api會在另一個線程處理,處理完成后會自動塞到j(luò)s的消息隊列里。
消息隊列又分為宏任務(wù)隊列和微任務(wù)隊列。
該機制將js分為同步任務(wù)和異步任務(wù)。
瀏覽器提供的api是宏任務(wù):setTimeout, setInterval,setImmediate, ajax, nextTick, requestAnimationFrame, UI render...
js引擎提供的是微任務(wù):promise, async/await...
script中的js代碼也是宏任務(wù)
執(zhí)行優(yōu)先級
同步任務(wù) => nextTick => 異步任務(wù) => setImmediate
從代碼執(zhí)行驗證上述理論
注意事項:
process.nextTick只在node環(huán)境中生效。
總結(jié)
在瀏覽器中事件循環(huán)除了js的處理還有ui線程的處理。每走完一輪js的便會走一遍ui的處理。以此往復形成事件循環(huán),但ui線程那塊暫時想不到演示示例,所以目前只演示了js這一塊。