最简单的eventLoop,同步和异步,宏任务和微任务

646 阅读4分钟

今天去看eventloop事件循环的时候,看了一些文章,越看越模糊,自己准备梳理一下自己能够理解的过程

js

在说这个流程之前,我们先来说一下,几个概念,同步代码,宏任务,微任务,栈,堆,同步任务,异步任务,单线程

大家都知道,js 是单线程,node 也是单线程,所谓的单线程就是同时只能做一件事情,其他的事情在后面排,像招商银行的客服一样,one by one and next 主线程就是 那个 单线程 但是要搞清楚,js是单线程,宿主环境可能不是单线程,浏览器可以是多线程,node环境是单线程

概念

同步代码 和 同步任务其实是一个概念,是执行器从上至下能立刻完成的事件,不会被引擎挂起、不需要过多损耗,发费过长的事件去完成的事件,同步任务的任务队列就放在栈里面,栈区存放的都是一些简单的事情,

异步任务,是浏览器在将来某个时间 或者说 以后满足某一条件等才会去执行的一个任务,它被放在了一个任务队列里面,当主线程处理完成后,会去处理任务队列的异步任务。

那么 不同的异步任务根据性质不一样,分为两类,就是 宏任务 和 微任务,所以,同步任务是包含两种任务,一种是宏任务,一种是微任务

宏任务 和 微任务 是怎么区分来着,为什么这个就是宏任务,这个就是微任务呢,这里说不得,太长了, 那就不管上面的概念,我记住哪一个是宏 和 微 就OK了,

这里写了一个表格,在node环境和js环境 不同的事件区分的任务种类还有些不一样

任务事件node环境浏览器环境
IO宏任务宏任务
setTimeOut,setInterVal
setImmediate
requestAnimationFrame宏任务
process.nextTick微任务
MutationObserver微任务
Promise.then catch finally微任务微任务
async/await函数中的后续操作微任务微任务

堆和栈: js代码执行的时候会将不同的变量存于内存中的不同位置就是堆栈的位置, 堆(heap)和栈(stack)

其中,堆里存放着一些对象。而栈中则存放着一些基础类型变量以及对象的指针。

怎么记忆他们呢,

堆,一堆,很多,存放的东西很多,就是一堆,就是堆, 引用数据类型,对象,存很多东西,放在这里,

其余的就是栈,栈中存放着一些基础类型变量以及对象的指针。相对比较简单一些的东西

但是执行栈 和 栈 是两个概念, 执行栈可以简单理解执行上下文的环境

ok, 概念简单说完了,说说整体的eventLoop

主线程会把同步任务(同步代码)依次执行,在执行同步代码的同时,可能会产生异步任务,可能是宏任务,也可能是微任务,把这些任务依次放进一个队列里面,在同步任务执行完成后,会去执行异步任务, 这里不说什么 monitoring process,Event table, Event queue , 简单点

好,同步代码执行完成,在此期间 ,会产生宏任务, 可能会有微任务, 如果有微任务,那么肯定是要先去执行微任务,再去执行宏任务

但是很多文章都是说,宏任务执行期间,如果有微任务进入,在当前的宏任务执行完毕后,优先执行剩下的微任务,微任务是紧急插入事件,需要优先执行,就是下面这张图

开头在哪里,异步任务应该有一个开头,如果开头有微任务,和宏任务呢,为啥不直接说呢

看的我心慌 ,到底是不是先执行微任务,在执行宏任务,

image.png

结论

那,结论就出来了: 主线程会把同步任务(同步代码)依次执行,在执行同步代码的同时,可能会产生异步任务,可能是宏任务,也可能是微任务,把这些任务依次放进一个队列里面,在同步任务执行完成后,会去执行异步任务,异步任务中,如果存在微任务,先执行微任务,在执行宏任务,如果在宏任务执行中产生了微任务,那么在本次宏任务执行完毕后,执行剩余的微任务,微任务中如果还存在微任务,接着执行,直到执行完毕,在去执行下一个宏任务。

额外的

说一些额外的:

  1. 异步任务不在主线程里面执行,在宿主环境执行,执行完的任务有回调函数,会放在队列里,按顺序依次等待主线程来执行(想想平时请求的接口)

  2. 宏任务和微任务放的不是一个队列,是两个队列,先执行的永远是微任务的队列

image.png

如有错误,还请指出,加以改正,感谢。