JavaScript运行机制—EventLoop

453 阅读2分钟

什么是EventLoop?

  • js为什么是单线程

    js采用单线程,和js的用途相关,js主要是用来操作浏览器中的dom元素;
    想象一下,如果js是多线程,不同的线程对同一个dom进行操作,一方面会增加浏览器渲染的复杂度;另一方面会造成浏览器的混乱,不知道如何是好😭
    所以js采用单线程的方式,之后也不会进行改变
    
  • 任务队列

    • 单线程的执行方式,意味着所有的任务都会在同一个主线程上面进行排队执行,形成了任务队列
    • js代码可以分为同步与异步代码,所以相应的会形成同步任务与异步任务,所谓的异步不会阻塞主线程,会等主线程的任务完成之后,再行执行
  • EventLoop

    • 浏览器为了提高效率,模拟多线程管理方式,在同步任务执行完毕之后,通过EventLoop方式获取异步任务执行,就形成了EventLoop

主执行栈

  • 如图所示,js中的内存分为 堆内存(heap) 和 栈内存(stack), 堆内存 中存的是我们声明的object类型的数据,栈内存中存的是基本数据类型以及 函数执行时的运行空间。我们的同步代码就放在执行栈 中,即主执行栈;那异步代码呢?浏览器会将 dom事件 ajax setTimeout等异步代码放到队列中,等待执行栈中的代码都执行完毕,才会执行队列中的代码。

异步队列

  • 异步代码存放的队列,但异步队列的执行也分为宏任务与微任务

宏任务

  • 宏任务包括setTimeOut、setInterval
  • 等待执行栈和微任务队列都执行完毕才会执行,并且在执行完每一个宏任务之后,会去看看微任务队列有没有新添加的任务,如果有,会先将微任务队列中的任务清空,才会继续执行下一个宏任务

微任务

  • 微任务包括Promise
  • 当执行栈中的代码执行完毕,会在执行宏任务队列之前先看看微任务队列中有没有任务,如果有会先将微任务队列中的任务清空才会去执行宏任务队列

代码执行的次序为:主执行栈 > 微任务 > 宏任务

举个🌰

setTimeout(() => {
    console.log('timeout1')
    Promise.resolve().then(() => {
        console.log('promise1')
    })
    Promise.resolve().then(() => {
        console.log('promise2')
    })
}, 100)

setTimeout(() => {
    console.log('timeout2')
    Promise.resolve().then(() => {
        console.log('promise3')
    })
}, 200)

输出结果:timeout1 promise1 promise2 timeout2 promise3

nodejs的EventLoop

  • nodejs中的执行机制,和上述浏览器中的执行机制有差异;和node的版本也有关系,等着下次再进行学习

参考链接