JavaScript 微任务和宏任务
toinghub 人气:0前言:
js是一门单线程语言,所以它本身是不可能异步的,但是js的宿主环境(比如浏览器、node)是多线程,宿主环境通过某种方式(事件驱动)使得js具备了异步的属性。而在js中,我们一般将所有的任务都分成两类,一种是同步任务,另外一种是异步任务。而在异步任务中,又有着更加细致的分类,那就是微任务和宏任务
1.概念
1.1宏任务
宏任务 ---- setTimeout
、setInterval
、DOM
事件、AJAX
请求
浏览器为了能够使得JS内部task与DOM
任务能够有序的执行,会在一个task
执行结束后,在下一个 task 执行开始前,对页面进行重新渲染 (task->渲染->task->…)
1.2微任务
微任务 ---- Promise
、async
/await
微任务通常来说就是需要在当前 同步任务 执行结束后立即执行的任务,比如对一系列动作做出反馈,或者是需要异步的执行任务而又不需要分配一个新的任务,这样便可以减小一点性能的开销。
2.执行顺序
先来看一段代码,在来探讨执行顺序:
console.log(1) setTimeout(() => { console.log(2) }) Promise.resolve().then(() => { console.log(3) }) console.log(4)
上面段代码打印的结果为1 4 3 2 。从上面代码,可以得出他们的执行顺序是:
先执行同步代码,遇到异步宏任务时候则将异步宏任务放入宏任务队列中,遇到异步微任务的时候则将异步微任务放入微任务列表中,当所有的同步代码执行完毕后,在将异步微任务从列表中调入主线程执行,异步微任务执行完毕之后再将异步宏任务从队列中调入主线程执行,一直循环到素有任务执行完毕。
注意:微任务执行下先于页面渲染的
3.任务关系
宏任务是主流,当js
开始被执行的时候,就是开启一个宏任务,在宏任务中执行一条一条的指令,宏任务可以同时拥有多个,但是会按照顺序一个一个执行。
每一个宏任务,后面都可以跟着一个微任务队列,如果微任务队列中有指令或者方法,则先执行。如果没有,则开始执行下一个宏任务,知道所有的宏任务执行完毕。
4.任务详解
为什么有了宏任务后,还是会有微任务的存在?那是因为宏任务太占用性能,当需要一些较早就准备好的方法,排在最后才执行的时候,又不想新增一个宏任务,那么就可以把这些方法,一个一个的放在微任务队列里面,在这个宏任务中的代码执行完后,就会执行微任务队列。
因此当前同步代码执行,遇到异步任务,如果是异步宏任务,放入下一轮宏任务队列,是异步微任务,放入微任务队列跟在当前宏任务屁股后面。微任务相当于宏任务的小尾巴,因此当前宏任务执行完,在它后面等着的异步微任务就会被立刻放入队列继续执行。而异步的宏任务需要等到下一轮,从而造成了异步中微任务在宏任务之前执行的情况。
加载全部内容