因為 js 是單線程運行的,在代碼執(zhí)行時,通過將不同函數(shù)的執(zhí)行上下文壓入執(zhí)行棧中來保證代碼的有序執(zhí)行。在執(zhí)行同步代碼時,如果遇到異步事件,js 引擎并不會一直等待其返回結(jié)果,而是會將這個事件掛起,繼續(xù)執(zhí)行執(zhí)行棧中的其他任務(wù)。當(dāng)異步事件執(zhí)行完畢后,再將異步事件對應(yīng)的回調(diào)加入到一個任務(wù)隊列中等待執(zhí)行。任務(wù)隊列可以分為宏任務(wù)隊列和微任務(wù)隊列,當(dāng)當(dāng)前執(zhí)行棧中的事件執(zhí)行完畢后,js 引擎首先會判斷微任務(wù)隊列中是否有任務(wù)可以執(zhí)行,如果有就將微任務(wù)隊首的事件壓入棧中執(zhí)行。當(dāng)微任務(wù)隊列中的任務(wù)都執(zhí)行完成后再去執(zhí)行宏任務(wù)隊列中的任務(wù)。
Event Loop 執(zhí)行順序如下所示:首先執(zhí)行同步代碼,這屬于宏任務(wù)當(dāng)執(zhí)行完所有同步代碼后,執(zhí)行棧為空,查詢是否有異步代碼需要執(zhí)行執(zhí)行所有微任務(wù)當(dāng)執(zhí)行完所有微任務(wù)后,如有必要會渲染頁面然后開始下一輪 Event Loop,執(zhí)行宏任務(wù)中的異步代碼