js的事件循环机制那些事

148 阅读2分钟

js单线程

js为什么是单线程的,这与js设计之初理念有关,js设计之初就是为了操纵DOM元素的,如果有多个线程都要修改同一个DOM元素的话,那么浏览器会如何执行呢?为了避免这一问题,js被设计为单线程延续至今。

同步与异步

由于js的单线程,在处理一些复杂逻辑的时候,下一个任务需要等待上一个任务执行完毕后才能继续。这也就是同步。同步很好理解,比如我们自己一个人想要做一顿饭,需要买菜,洗菜,炒菜,需要一步一步进行,这即是同步,异步就是我同时也要吃主食,我可以在煮饭的同时,去做菜,这样在菜做好了,饭也好了,煮饭这一过程可以理解为一个异步。同步很好理解,从上到下依次执行即为同步,那么js中异步是怎么实现的呢?可以参考如下,这里不再做过多解释js几种异步实现方式

事件循环

网上看了很多,我用我自己的理解来解释一下,首先有一个执行栈,这个也就是主线程执行的地方,所有进程最终都在这里完成,也就是先执行所有的同步代码,碰到异步的时候,开辟一个子线程去执行这个异步代码,等他执行完毕后,还有一个重要概念-事件队列,执行完毕的异步事件进入事件队列等待执行栈空后,被拿到执行栈中执行,循环往复,直到所有任务执行完毕,事件循环结束。

宏任务与微任务

我的理解是异步事件分为两种,宏任务与微任务,宏任务就像setTimeout、setInterval等,他们就会像之前一样执行完成后进入事件队列等待主线程空闲后来调用,但是在将宏任务拿到主线程之前,会先检查是否有微任务,如果有将为任务拿到执行栈执行,然后进行渲染,在执行下一次宏任务,我的理解最终执行就是分以下几步

  • 先跑执行栈中的同步代码,碰到异步扔到子进程去执行
  • 异步任务分为宏任务和微任务(promise、process.nextTick)
  • 当宏任务执行完毕后进入事件队列等待执行栈空闲
  • 微任务在微任务队列中执行完毕后等待当前执行栈中宏任务跑完后直接调用
  • 在执行栈空时他会直接跑完所有微任务,然后进行页面渲染
  • 之后再去任务队列取宏任务执行,循环往复