美文网首页Web前端之路
JavaScript中的Event Loop小理解

JavaScript中的Event Loop小理解

作者: jaimor | 来源:发表于2020-03-06 15:26 被阅读0次
    我也不知道这是个啥图

    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, ...]

    好了,开始装了...

    1. 首先,执行栈还是会先执行宏任务,那就去宏任务列表中取,此时的macList = [script],所以取出script执行,macList = []。
    2. 输出 start。
    3. 遇到setTimout,将回掉加入到宏任务列表中,macList = [setTimeoutCallbackFunc1]。
    4. 执行new Promise代码,输出 new Promise,然后遇到setTimeout,加入到红任务列表中,macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2],然后又遇到resolve,将其回掉加入到微任务列表,micList = [promiseThenCallbackFunc1]。
    5. (请先预备async/await知识)执行asyncFunc1函数,则输出 asyncFunc1 start,遇到 await asyncFunc2(),则先执行函数,输出asyncFunc2,然后返回了一个new Promise,new Promise中的代码回立马执行,遇到了setTimeout,加入到宏任务队列,macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2, setTimeoutCallbackFunc3],而后返回到asyncFunc1中,后边的代码会全部被封装到then中,直到asyncFunc2中resolve才会被执行。
    6. 第5点结束,asyncFunc1执行也就结束,然后输出 end。
    7. 至此,本轮宏任务结束,输出了 start, new Promise, asyncFunc1 start, asyncFunc2, end。开始执行微任务。
    8. 然后开始微任务列表挨个执行。此时micList = [promiseThenCallbackFunc1],取出promiseThenCallbackFunc1执行,输出 promise then。微任务队列执行完毕,再次执行宏任务。
    9. 此时宏任务列表macList = [setTimeoutCallbackFunc1, setTimeoutCallbackFunc2, setTimeoutCallbackFunc3]。挨个取出执行。
    10. 执行setTimeoutCallbackFunc1,输出 setTimout
    11. 执行setTimeoutCallbackFunc2,输出 new Promise setTimout
    12. 执行setTimeoutCallbackFunc3,输出 asyncFunc2 promise,但此时又遇到resolve,此时会将await asyncFunc2()后的代码当作回掉,加入到微任务列表中micList = [console.log("asyncFunc1 end")]。宏任务队列又执行完毕,又开始执行微任务。
    13. 此时微任务micList = [console.log("asyncFunc1 end")],取出执行,输出 asyncFunc1 end。此时全部执行完毕。

    done!!!!
    理解得不深,如有错误,赶紧指正,非常感谢!!!

    相关文章

      网友评论

        本文标题:JavaScript中的Event Loop小理解

        本文链接:https://www.haomeiwen.com/subject/wocirhtx.html