美文网首页
Javascript的事件循环

Javascript的事件循环

作者: _hider | 来源:发表于2020-06-16 17:40 被阅读0次

javascript事件循环是执行栈,还有微任务和宏任务之间的关联,看了很多网上的文章,大多对事件循环秉持的观点如下:

执行栈执行同步代码,宏任务和微任务执行异步代码。执行栈中同步代码执行完毕之后,再执行微任务队列,等微任务队列执行完毕后,再执行宏任务队列,然后再执行微任务对列循环往复执行。

先不说改观点是对是错,先看宏任务和微任务既然都是执行异步代码的消息队列,两者又有什么区别:

  • 宏任务macrotaskscript(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
  • 微任务microtaskprocess.nextTick, Promise, Object.observe(已废弃)。

宏任务中有script(整体代码),这个就比较疑惑了?如果script(整体代码)是宏任务的话,那肯定是宏任务先执行,因为script(整体代码)在一开始就会执行。在之前的观点中明明是微任务先执行,然后再执行宏任务,这个就比较矛盾了。所以以上的观点是值得商榷的,事件循环从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的微任务。当所有可执行的微任务执行完毕之后。循环再次从宏任务开始,找到其中一个任务队列执行完毕,然后再执行所有的微任务,这样一直循环下去。

看一道经典的面试题来加深事件循环的理解:

<script>
    let timer1 = setTimeout(() => console.log('setTimeout1'), 0);  //1宏任务
    let timer2 = setTimeout(() => { //2宏任务
        console.log('setTimeout2');
        let promise2 = Promise.resolve().then(() => { //2微任务
            console.log('promise3');
            let promise3 = Promise.resolve().then(() => { //3微任务
                console.log('promise4');
            });
            console.log(5);
        });
        let timer4 = setTimeout(() => console.log('setTimeout4'), 0);  //4宏任务
    }, 0);
    let timer3 = setTimeout(() => console.log('setTimeout3'), 0);  //3宏任务
    console.log("console1")
    let promise1 = Promise.resolve().then(() => {  //1微任务
        console.log('promise1');
    });
</script>
  1. 开始script整体代码执行宏任务。
  2. timer1,timer2,timer3是异步代码,依次进入宏任务队列等待执行。
  3. 同步代码入执行栈,输出console1
  4. 接下来是promise1,进入微任务队列并执行,输出promise1
  5. 第一轮宏任务循环结束,开始第二轮宏任务,timer1执行并输出setTimeout1
  6. 第二轮宏任务结束,开始第三轮宏任务,执行timer2,代码如下:
let timer2 = setTimeout(() => { //2宏任务
    console.log('setTimeout2');
    let promise2 = Promise.resolve().then(() => { //2微任务
        console.log('promise3');
        let promise3 = Promise.resolve().then(() => { //3微任务
            console.log('promise4');
        });
        console.log(5);
    });
    let timer4 = setTimeout(() => console.log('setTimeout4'), 0);  //4宏任务
}, 0);
  1. 同步代码入执行栈,执行并输出setTimeout2
  2. promise2进入微任务队列开始执行,执行同步代码,依次输出promise35
  3. promise3进入微任务队列开始执行,输出promise4,要注意的是当结束一轮宏任务之后,必须执行当前所有的微任务,才能进入下一轮宏任务。
  4. 然后发现该轮宏任务循环还有个timer4,排入宏任务队列。
  5. 因为队列是先进先出,timer3timer4先进入宏任务队列,所以先执行timer3,输出setTimeout3
  6. 最后执行timer4,输出setTimeout4

相关文章

  • Js事件循环

    列表 JavaScript事件循环 测试金字塔 stub JavaScript事件循环理解 javaScript语...

  • iOS RunLoop由浅入深

    Event Loop Event Loop事件循环机制,如javascript的事件循环,以及依赖其的nodejs...

  • JavaScript事件循环

    js是一门单线程的语言,不可能进行多线程编程,异步编程就是多线程编程一种模式,但是我们经常讲到js的异步编程,其实...

  • JavaScript - 事件循环

    前言 JavaScript是一门单线程、非阻塞的脚本语言。 单线程意味着javascript代码在执行的任何时候,...

  • javascript事件循环

    EventLoop 以下内容仅限于自己理解,可能并不全面或者有错误 参考文档:https://www.cnblog...

  • JavaScript事件循环

    解释JavaScript的事件循环 这个帖子关于什么 浏览器普遍将JavaScript作为脚本语言,这篇文章有利于...

  • javascript事件循环

    异步任务栈分为: 宏任务(macrotask): setTimeout setImmediate setInter...

  • JavaScript事件循环

    事件循环是什么?事实上我把事件循环理解成我们编写的JavaScript和浏览器或者Node之间的一个桥梁。 浏览器...

  • JavaScript事件循环

    为什么js是单线程 JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用...

  • JavaScript事件循环

    Tasks(任务),microtasks(微任务),queues(队列),schedules(调度): 举个例子:...

网友评论

      本文标题:Javascript的事件循环

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