JavaScript中的Event Loop小理解

我也不知道這是個啥圖

Event Loop

Event Loop定義了瀏覽器執(zhí)行你寫的代碼的順序。我們都知道瀏覽器在執(zhí)行代碼的時候,并不一定按照你寫的順序來執(zhí)行,因為這里邊可能存在異步執(zhí)行,而且可能有多個異步代碼,還有可能有多種異步代碼。那么當這種情況存在的時候,瀏覽器就需要有一種機制,來判斷當前應當執(zhí)行哪部分代碼。
然后,還需要知道Event Loop機制中兩個任務(wù),第一個是宏任務(wù)MacroTask,第二個是微任務(wù)MicroTask,還有一個叫執(zhí)行棧的東西。Event Loop的機制就是先讓執(zhí)行棧執(zhí)行完宏任務(wù)隊列中的所有任務(wù),然后再執(zhí)行微任務(wù)隊列中的所有任務(wù),完了繼續(xù)循環(huán)。

  • 執(zhí)行棧:所有的js代碼都會被放到執(zhí)行棧中依次執(zhí)行。
  • 宏任務(wù):簡單點說,就是一串js代碼,但是被劃分為了宏任務(wù)。哪些會被劃分為宏任務(wù)呢?包括script標簽中代碼 setTimeout setInterval I/O UI渲染 postMessage等(并沒有歸納完)。宏任務(wù)可以繼續(xù)產(chǎn)生宏任務(wù)/微任務(wù)。
  • 微任務(wù):同理,也是一串被劃分為微任務(wù)的js代碼。包括Promise中的resolve/reject async/await process.nextTick等(并沒有歸納完)。同樣,微任務(wù)也可以繼續(xù)產(chǎn)生宏任務(wù)/微任務(wù)。
    廢話少說,趕緊聚個例子:
//先來個簡單點的
console.log("start");
setTimeout(_ => console.log("setTimeout"), 0);
console.log("end");
// start
// end
// setTimout
//解釋不?算了不解釋了
// 第二個例子,還是簡單點
console.log("start");
setTimeout(_ => console.log("setTimeout"), 0);
new Promise(resolve => {
  console.log("new Promise");
  resolve("promise then");
}).then(res => console.log(res));
console.log("end");
// start
// new Promise
// end
//promise then
// setTimeout
//解釋不?還是解釋哈嘛……
/* 是弄個子的
1.執(zhí)行棧會首先去拿宏任務(wù)列表中的代碼塊來執(zhí)行,此時只有script標簽代碼,所以就拿過來執(zhí)行咯喲
2.執(zhí)行第一句,輸出 start
3.執(zhí)行第二句,遇到了setTimeout,此時會將其回掉任務(wù)加入到下一輪的宏任務(wù)中
4.new Promise中的代碼直接執(zhí)行(為什么直接執(zhí)行,請看Promise相關(guān)知識),
輸出 new Promise,完了遇到了resolve代碼,此時會將其回掉任務(wù)加入到下一輪微任務(wù)中
5.輸出 end,此時,本輪宏任務(wù)執(zhí)行完畢,開始執(zhí)行微任務(wù)
6.由上可知,微任務(wù)中第一條(也僅此一條)是resolve的回掉,所以拿出來執(zhí)行,輸出 promise then
7.微任務(wù)執(zhí)行完了,再次執(zhí)行宏任務(wù),也從第一條開始,輸出setTimeout
8.done!!!
*/
//第三個例子,不難,只是多增加了兩位新客人而已
console.log("start");
setTimeout(_ => console.log("setTimeout"), 0);
new Promise(resolve => {
  console.log("new Promise");
  setTimeout(_ => console.log("new Promise setTimeout"), 0);
  resolve("promise then");
}).then(res => console.log(res));
async function asyncFunc1() {
  console.log("asyncFunc1 start");
  await asyncFunc2();
  console.log("asyncFunc1 end");
}
async function asyncFunc2() {
  console.log("asyncFunc2");
}
asyncFunc1();
console.log("end");
/* 先補充哈async/await的只是哈 */ /* 開始補充... */ /* 補充完畢 */
//輸出
//start
//new Promise
//asyncFunc1 start
//asyncFunc2
//end
//promise then
//asyncFunc1 end
//setTimeout
//new Promise setTimeout
/* 不用解釋了,只要曉得 async/await 而且李杰了上一個例子,那就沒問題了 */
// 第四個例子
console.log("start");
setTimeout(function setTimeoutCallbackFunc1() {console.log("setTimeout")}, 0);
new Promise(resolve => {
  console.log("new Promise");
  setTimeout(function setTimeoutCallbackFunc2() {console.log("new Promise setTimeout")}, 0);
  resolve("promise then");
}).then(function promiseThenCallbackFunc1(res) {console.log(res)});
async function asyncFunc1() {
  console.log("asyncFunc1 start");
  await asyncFunc2();
  console.log("asyncFunc1 end");
}
async function asyncFunc2() {
  console.log("asyncFunc2");
  return new Promise(resolve => {
    setTimeout(function setTimeoutCallbackFunc3() {
      console.log("asyncFunc2 promise");
      resolve();
    }, 0);
  })
}
asyncFunc1();
console.log("end");
//這又輸出什么呢?這個可以說一哈,至于輸出啥子,稍等哈,我復制到瀏覽器執(zhí)行哈...
// 執(zhí)行完了,輸出
// start
// new Promise
// asyncFunc1 start
// asyncFunc2
// end
// promise then
// setTimeout
// new Promise setTimeout
// asyncFunc2 promise
// asyncFunc1 end
/* 終于打完了 */ /* 雖然我在瀏覽器中執(zhí)行后照到打的,但是我能解釋清楚 */ /* 開始裝... */

為了形象點,畫圖又不會,咋個搞呢?搞個都看得懂的

  • macList = [] //宏任務(wù)隊列
  • micList = [] //微任務(wù)隊列
  • 比如:macList = [task1, task2, task3, task4, task5, ...]

好了,開始裝了...

  1. 首先,執(zhí)行棧還是會先執(zhí)行宏任務(wù),那就去宏任務(wù)列表中取,此時的macList = [script],所以取出script執(zhí)行,macList = []。
  2. 輸出 start。
  3. 遇到setTimout,將回掉加入到宏任務(wù)列表中,macList = [setTimeoutCallbackFunc1]。
  4. 執(zhí)行new Promise代碼,輸出 new Promise,然后遇到setTimeout,加入到紅任務(wù)列表中,macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2],然后又遇到resolve,將其回掉加入到微任務(wù)列表,micList = [promiseThenCallbackFunc1]。
  5. (請先預備async/await知識)執(zhí)行asyncFunc1函數(shù),則輸出 asyncFunc1 start,遇到 await asyncFunc2(),則先執(zhí)行函數(shù),輸出asyncFunc2,然后返回了一個new Promise,new Promise中的代碼回立馬執(zhí)行,遇到了setTimeout,加入到宏任務(wù)隊列,macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2, setTimeoutCallbackFunc3],而后返回到asyncFunc1中,后邊的代碼會全部被封裝到then中,直到asyncFunc2中resolve才會被執(zhí)行。
  6. 第5點結(jié)束,asyncFunc1執(zhí)行也就結(jié)束,然后輸出 end。
  7. 至此,本輪宏任務(wù)結(jié)束,輸出了 start, new Promise, asyncFunc1 start, asyncFunc2, end。開始執(zhí)行微任務(wù)。
  8. 然后開始微任務(wù)列表挨個執(zhí)行。此時micList = [promiseThenCallbackFunc1],取出promiseThenCallbackFunc1執(zhí)行,輸出 promise then。微任務(wù)隊列執(zhí)行完畢,再次執(zhí)行宏任務(wù)。
  9. 此時宏任務(wù)列表macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2, setTimeoutCallbackFunc3]。挨個取出執(zhí)行。
  10. 執(zhí)行setTimeoutCallbackFunc1,輸出 setTimout
  11. 執(zhí)行setTimeoutCallbackFunc2,輸出 new Promise setTimout
  12. 執(zhí)行setTimeoutCallbackFunc3,輸出 asyncFunc2 promise,但此時又遇到resolve,此時會將await asyncFunc2()后的代碼當作回掉,加入到微任務(wù)列表中micList = [console.log("asyncFunc1 end")]。宏任務(wù)隊列又執(zhí)行完畢,又開始執(zhí)行微任務(wù)。
  13. 此時微任務(wù)micList = [console.log("asyncFunc1 end")],取出執(zhí)行,輸出 asyncFunc1 end。此時全部執(zhí)行完畢。

done!!!!
理解得不深,如有錯誤,趕緊指正,非常感謝?。?!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容