js中的宏观任务和微观任务

JavaScript08

js中的宏观任务和微观任务,第1张

1.宏观任务(macro task): 由宿主(node、浏览器) 发起的任务,如setTimeOut、setInterval、setImmediate、I/O

2.微观任务(micro task):由 js引擎 发起的任务,如process.nextTick、promise、mutationObserver

最近几天,面试了几个应聘的。有一道面试题,答案真是千奇百怪。就是这么一道题:

setTimeout(() =>{

console.log("setTimeout")

})

let p1 =new Promise((resolve) =>{

console.log("Promise1")

    resolve("Promise2")

})

p1.then((res) =>{

console.log(res)

})

console.log("over")

当然有的答对的可能是见过这么一道相似的类似题目,我们来简单聊一聊这是一道什么样的题。

接触JS的肯定都知道,JS是单线程的。而单线程就意味着所有的任务都要进行排队,依次执行,这就是任务队列。但是会有那样的任务执行起来很耗时间,而我们还有很多没有利用的CPU空间。所以就产生了:JS中任务是有同步(synchronous)和异步(asynchronous)的分别的。同步就是顺次执行的那一种,而异步就是需要等待的那一种。同步和异步的执行路线是不同的:同步会进入主线程顺次执行。只有前一个执行结束才会执行下一个;而异步会进入一个等待的队列,可以理解为等待中的任务队列(任务队列就是一个先进先出的队列结构,主线程的执行队列的读取是自动的)。在这里异步任务会在Event Table中注册相应的回调函数。当指定的步骤完成了,Event Table会将注册了的回调函数推送到Event Queue,在Event Queue这里进行等待上场。当主线程内的任务执行完毕为空之后,就会到Event Queue读取相应的函数,进入主线程执行。这个过程不断重复构成Event Loop。

这个就是同步与异步的简单过程。

但是,会有一个疑问,向上面的那道题目中的SetTimeout和promise都是异步任务那他俩的执行属性呢?难道是顺次,这个还真不一定。

JS的异步也是有一个机制的,就是会分为宏任务和微任务。宏任务和微任务会放到不同的event queue中,先将所有的宏任务放到一个event queue,再将微任务放到一个event queue中。执行完宏任务之后,就会先从微任务中取这个回调函数执行。

那么什么是宏任务呢,一般就是setTimeout、setInterval、script、I/O

微任务就是,Promise\process.nextTick

让我们回到那道题,首先会执行script下的宏任务,解析,遇到setTimeout,判断它是一个宏任务类型,将其放到一个宏任务的queue中;遇到Promise,开始执行,打印 Promise1 ;往下遇到then,判断是个微任务,放到微任务的队列中,等待执行;继续解析,打印 over 。查证本轮次的宏任务都执行完毕了,开始执行本轮的微任务,发现有一个then的回调函数,打印 Promise2 , 到这里微任务页执行完毕了,这样本轮次的Loop全部执行完毕,开始下一轮次的Loop。发现宏任务的队列有一个setTimeout的回调函数,打印 setTimeout 。