宏任务与微任务的区别

1、什么是宏任务(MacroTask)

宏任务包括:setTimeout setInterval Ajax DOM事件,
宏任务是由宿主(浏览器、Node)发起的,宏任务,可以理解为每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行).进程的切换肯定是宏任务,因为需要花费大量的资源

2、什么是微任务(MicroTask)

微任务包括:Promise async/await 等…
微任务是由JS引擎发起的,微任务,可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。线程的切换是微任务,因为只需要在同一个进程中切换就可以了

3、宏任务和微任务是怎么执行的?

执行顺序:主线程 >> 主线程上创建的微任务 >> 主线程上创建的宏任务

在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:

(1)执行一个宏任务(栈中没有就从事件队列中获取)

(2)执行过程中如果遇到微任务,就将它添加到微任务的任务队列中

(3)宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)

(4)当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染

(5)渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

我们通过一个流程图能更好的解释:

这里容易产生一个错误的认识

就是微任务先于宏任务执行。实际上是先执行同步任务,异步任务有宏任务和微任务两种,先将宏任务添加到宏任务队列中,将宏任务里面的微任务添加到微任务队列中。所有同步执行完之后执行异步,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行。之后就一直循环…

在这里插入图片描述

4、同步和异步

1.两者都是异步

2.同步和异步的区别:

(1)同步代码执行:你写的顺序是什么,他就按什么顺序执行,显而易见,同步任务是阻塞的,也就是说,只有前一句执行完成之后,才能进行下一句

(2)异步代码的执行:常见的异步就是callback,不是按照写的顺序执行的就是异步,但是异步并不等于非阻塞,callback被调用的时机也是通过执行到它才会被执行,也是一步步往下执行的,只不过不是按照写的程序从上到下的顺序而已,所以如果有些任务占用了整个线程,那么异步任务也会被阻塞,这也是由于JS都是单进程单线程的

(3)经典的JS都是单进程单线程的,单现代的JS已经突破了这一点,我们有方法新建额外地进程共同处理任务,NodeJS也可以在同一个进程中新建线程,浏览器也有要支持线程的计划

(4)异步除了回调,还有其他种类的,比如任务,任务是一种队列类型的,先注册的任务先被执行,任务里面,根据执行的时机分为宏任务和微任务,根据什么区分发执行时机,需要去看设计部分

5、为什么定时器、事件是宏任务

(1)事件为什么是宏任务呢?

事件的触发是依赖于浏览器的实现,平台有它自己的事件注册和派发机制,比如nodeJS用的内核libuv,所以不管怎样,事件的独立注册表和派发机制导致,他也不会和JS存在一个进程中,事件的管理中心一定是在另外一个进程中实现的,那么去派发事件,也就是宏任务

(2)为什么定时器任务是宏任务?
(1)可以把定时器和定时器任务是分离的,先把定时器想成一个时间管理中心

(2)然后在上面注册一个个任务,这些任务本身和时间无关

(3)时间管理中心和时间有关的,当时间管理中心发现时间到了,要执行任务,就从任务列表中找出注册的任务,并通知JS执行任务

(4)所以可以看到,时间管理中心(定时器的进程)和执行的任务(JS运行时)是无关的,不共享上下文,所以是宏任务

(5)控制渲染的函数如requestAnimationFrame,这个函数本身是要求在下一帧重绘前做什么,它的本身被设计成是在渲染的流程中,然后它做的事情应该也是和渲染有关的,也就是这个任务和它所处的空间的上下文一致

猜你喜欢

转载自blog.csdn.net/qq_44734358/article/details/129097094
今日推荐