美文网首页
Javascript 事件循环eventLoop

Javascript 事件循环eventLoop

作者: 我是一个前端 | 来源:发表于2019-01-15 17:53 被阅读0次

    都知道javascript是单线程,那么问题来了,既然是单线程顺序执行,那怎么做到异步的?

    我们理解的单线程应该是这样的,排着一个个来,是同步执行。
    in-the-queue.jpg

    现实中js是这样的

            //没带身份证的 (去宏任务队列)
            setTimeout(function() {
                console.log(1);
            });
            
            new Promise(function(resolve, reject) {
                //都准备好的
                console.log(2)
                resolve(3)
            //没带钱的 (去微任务队列)
            }).then(function(val) {
                console.log(val);
            })
            //都准备好的
            console.log(4)
            //执行结果为 2、4、3、1
    

    结果告诉我们,js是单线程没错,不过不是逐行同步执行。

    那我们就来解析一下既然有异步,那顺序是怎样的?这些执行顺序规则就是理解eventLoop的要点,继续往下。

    Kapture 2019-01-15 at 16.01.35.gif

    上图为我录制的chrome控制代码台执行顺序,虽然能看出执行顺序但我们还是懵逼的,我们不知道规则,不懂就要问。

    搜索了很多官方、个人博客得到了一堆词:js引擎、主线程、事件表、事件队列、宏任务、微任务,彻底懵逼。。。

    不急不急一个个来,我们进入刨根问底状态

    js引擎

    总结一句话就是解析优化代码 **制定执行规则 具体规则往下看

    主线程

    总结一句话执行js引擎优化并排列顺序后的代码

    事件表(event table)

    执行代码过程中,异步的回调,例如(setTimeout,ajax回调)注册回调事件到event table

    事件队列

    当事件回调结束,事件表(event table)会将事件移入到事件队列(event queue)

    宏任务和微任务

    宏任务包含的事件
    事件 浏览器 node
    I/O
    setTimeout
    setInterval
    setImmediate
    requestAnimationFrame
    微任务包含的事件
    事件 浏览器 node
    I/O
    process.nextTick
    MutationObserver
    Promise.then catch finally

    很多博客是这样说的:
    浏览器会不断从task队列中按顺序取task执行,每执行完一个task都会检查microtask队列是否为空(执行完一个task的具体标志是函数执行栈为空),如果不为空则会一次性执行完所有microtask。然后再进入下一个循环去task队列中取下一个task执行

    说实话不是太理解,那么我就以自己的方式去学习和理解

    为了更好的理解我们再看代码

            console.log('1');
            setTimeout(function() {
                console.log('2');
                new Promise(function(resolve) {
                    console.log('3');
                    resolve();
                }).then(function() {
                    console.log('4')
                })
            })
            new Promise(function(resolve) {
                console.log('5');
                resolve();
            }).then(function() {
                console.log('6')
            })
    
            setTimeout(function() {
                console.log('7');
                new Promise(function(resolve) {
                    console.log('8');
                    resolve();
                }).then(function() {
                    console.log('9')
                })
            })
            //执行结果:1、5、6、2、3、4、7、8、9
    
    image.png

    有图为证我没骗你
    再来个动图我们具体看看浏览器的执行顺序


    eventLoop1.gif

    首先js引擎,区分是直接执行(同步代码),再执行异步代码,如果是异步再区分是宏任务还是微任务,分别放入两个任务队列,然后开始执行,每执行完一个宏任务,扫一遍微任务队列并全部执行,此时形成一次eventLoop循环。以此规则不停的执行下去就是我们所听到的事件循环。

    我再补充一点,可以理解js引擎一开始把整个script当做一个宏任务,这样里边的就更容易理解了,开始就执行script宏任务,解析到宏任务里边又包含同步代码和异步代码(宏任务和微任务)依次执行顺序形成eventLoop。

    欢迎吐槽点赞评论!

    文章参考学习:
    https://www.jianshu.com/p/12b9f73c5a4f
    https://juejin.im/post/59e85eebf265da430d571f89
    https://segmentfault.com/a/1190000013861128

    相关文章

      网友评论

          本文标题:Javascript 事件循环eventLoop

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