JavaScript中的Event Loop小理解

我也不知道这是个啥图 Event Loop Event Loop定义了浏览器执行你写的代码的顺序。我们都知道浏览器在执行代码的时候,并不一定按照你写的顺序来执行,因为这里边可能存在异步执行,而且可能有多个异步代码,还有可能有多种异步代码。那么当这种情况存在的时候,浏览器就需要有一种机制,来判断当前应当执行哪部分代码。 然后,还需要知道Event Loop机制中两个任务,第一个是宏任务MacroTask,第二个是微任务MicroTask,还有一个叫执行栈的东西。Event Loop的机制就是先让执行栈执行完宏任务队列中的所有任务,然后再执行微任务队列中的所有任务,完了继续循环。 执行栈:所有的js代码都会被放到执行栈中依次执行。 宏任务:简单点说,就是一串js代码,但是被划分为了宏任务。哪些会被划分为宏任务呢?包括script标签中代码 setTimeout setInterval I/O UI渲染 postMessage等(并没有归纳完)。宏任务可以继续产生宏任务/微任务。 微任务:同理,也是一串被划分为微任务的js代码。包括Promise中的resolve/reject async/await process.nextTick等(并没有归纳完)。同样,微任务也可以继续产生宏任务/微任务。 废话少说,赶紧聚个例子: //先来个简单点的 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.执行栈会首先去拿宏任务列表中的代码块来执行,此时只有script标签代码,所以就拿过来执行咯哟 2.执行第一句,输出 start 3.执行第二句,遇到了setTimeout,此时会将其回掉任务加入到下一轮的宏任务中 4.new Promise中的代码直接执行(为什么直接执行,请看Promise相关知识), 输出 new Promise,完了遇到了resolve代码,此时会将其回掉任务加入到下一轮微任务中 5.输出 end,此时,本轮宏任务执行完毕,开始执行微任务 6.由上可知,微任务中第一条(也仅此一条)是resolve的回掉,所以拿出来执行,输出 promise then 7.微任务执行完了,再次执行宏任务,也从第一条开始,输出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"); //这又输出什么呢?这个可以说一哈,至于输出啥子,稍等哈,我复制到浏览器执行哈... // 执行完了,输出 // start // new Promise // asyncFunc1 start // asyncFunc2 // end // promise then // setTimeout // new Promise setTimeout // asyncFunc2 promise // asyncFunc1 end /* 终于打完了 */ /* 虽然我在浏览器中执行后照到打的,但是我能解释清楚 */ /* 开始装... */ 为了形象点,画图又不会,咋个搞呢?搞个都看得懂的 macList = [] //宏任务队列 micList = [] //微任务队列 比如:macList = [task1, task2, task3, task4, task5, ...] 好了,开始装了... 首先,执行栈还是会先执行宏任务,那就去宏任务列表中取,此时的macList = [script],所以取出script执行,macList = []。 输出 start。 遇到setTimout,将回掉加入到宏任务列表中,macList = [setTimeoutCallbackFunc1]。 执行new Promise代码,输出 new Promise,然后遇到setTimeout,加入到红任务列表中,macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2],然后又遇到resolve,将其回掉加入到微任务列表,micList = [promiseThenCallbackFunc1]。 (请先预备async/await知识)执行asyncFunc1函数,则输出 asyncFunc1 start,遇到 await asyncFunc2(),则先执行函数,输出asyncFunc2,然后返回了一个new Promise,new Promise中的代码回立马执行,遇到了setTimeout,加入到宏任务队列,macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2, setTimeoutCallbackFunc3],而后返回到asyncFunc1中,后边的代码会全部被封装到then中,直到asyncFunc2中resolve才会被执行。 第5点结束,asyncFunc1执行也就结束,然后输出 end。 至此,本轮宏任务结束,输出了 start, new Promise, asyncFunc1 start, asyncFunc2, end。开始执行微任务。 然后开始微任务列表挨个执行。此时micList = [promiseThenCallbackFunc1],取出promiseThenCallbackFunc1执行,输出 promise then。微任务队列执行完毕,再次执行宏任务。 此时宏任务列表macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2, setTimeoutCallbackFunc3]。挨个取出执行。 执行setTimeoutCallbackFunc1,输出 setTimout 执行setTimeoutCallbackFunc2,输出 new Promise setTimout 执行setTimeoutCallbackFunc3,输出 asyncFunc2 promise,但此时又遇到resolve,此时会将await asyncFunc2()后的代码当作回掉,加入到微任务列表中micList = [console.log("asyncFunc1 end")]。宏任务队列又执行完毕,又开始执行微任务。 此时微任务micList = [console.log("asyncFunc1 end")],取出执行,输出 asyncFunc1 end。此时全部执行完毕。 done!!!! 理解得不深,如有错误,赶紧指正,非常感谢!!!

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):