美文网首页IT知识
javascript事件循环机制

javascript事件循环机制

作者: Ming_Hu | 来源:发表于2019-07-10 23:32 被阅读1次

    javascript是一门单线程的非阻塞的脚本语言。单线程意味着javascript在执行代码的任何时候,都只有一个主线程来处理所有的任务。

    那么javascript引擎是如何实现这一点的呢?

    因为事件循环(event loop)。先上图:

    event_loop

    图片解读:

    • 同步和异步任务分别进入不同的执行场所,同步的进入主线程,异步的进入Event Table并注册函数
    • 当指定的事情完成时(重点)Event Table会将这个函数移入Event Queue
    • 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行
    • 上述的过程会不断的重复,也就是常常说的Event Loop(事件循环)

    简单例子

    我们来一个简单的例子来说明下:

    console.log('1');
    setTimeout(() => {
        console.log('2');
    }, 0)
    console.log('3');
    

    上面的代码将输出下面的结果:

    1
    3
    2
    

    因为setTimeout是一个异步的任务,所以会在最后才执行。

    那么,我们来个复杂点的例子:

    复杂例子

     console.log('1');
     setTimeout(() => {
        console.log('2')
     }, 1000);
     new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('3');
        }, 0);
        console.log('4');
        resolve();
        console.log('5');
     }).then(() => {
        console.log('6');
     });
     console.log('7');
    

    上面的代码输出的结果是:

    1
    4
    5
    7
    6
    3
    2
    

    看到这代码的时候是不是有些蒙圈?在我们揭开谜底之前,先来了解下微任务和宏任务

    微任务和宏任务

    微任务和宏任务都是异步的任务,他们都属于一个队列,主要区别是它们的执行顺序--微任务会比宏任务先执行。

    宏任务包含有:setTimeout, setInterval, setImmediate, I/O, UI rendering

    微任务包含有:process.nextTick, promise.then, MutationObserver

    嗯~回到上面的代码,如下:

     console.log('1');
     setTimeout(() => {
        console.log('2')
     }, 1000);
     new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('3');
        }, 0);
        console.log('4');
        resolve();
        console.log('5');
     }).then(() => {
        console.log('6');
     });
     console.log('7');
    

    在执行到new Promise的时候会立马新建一个promise对象并立即执行。所以会输出 1,4,5,而then则会在Event Table中注册成回调函数并放在微任务队列中,而两个setTimeout(输出3)和setTimeout(输出2,1s后完成的啊)会被先后注册成回调函数并放在宏任务队列中。

    理解了上面的一些原理之后,我们再来练下手...

    console.log(1)
    process.nextTick(() => {
      console.log(8)
      setTimeout(() => {
        console.log(9)
      })
    })
    setTimeout(() => {
      console.log(2)
      new Promise(() => {
        console.log(11)
      })
    })
    let promise = new Promise((resolve,reject) => {
      setTimeout(() => {
        console.log(10)
      })
      resolve()
      console.log(4)
    })
    fn()
    console.log(3)
    promise.then(() => {
      console.log(12)
    })
    function fn(){
      console.log(6)
    }
    

    得到的结果是:

    1
    4
    6
    3
    8
    12
    2
    11
    10
    9
    

    客官可以画下图整理下思路,然后代码运行验证一下啊💨

    参考&后话

    文章首发javascript事件循环机制,更多的内容,请戳我的博客进行了解,能留个star就更好了💨

    相关文章

      网友评论

        本文标题:javascript事件循环机制

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