是什么
宏任务和微任务是异步里api的分类;
1.微任务是es提供的api,常用的有: promise实例.then().catch() & 异步函数中await 行后面的代码 ;
2.宏任务是浏览器提供的api ,常用的有 :定时器 & ajax & dom事件;
宏任务和微任务的区别:
宏任务:dom渲染后触发
微任务:dom渲染前触发
js代码的执行顺序
简单理解: (只是做题记住这些就行了)
第1轮宏任务 (all同步代码,包括异步函数与promise)
->第1轮微任务 (await行后的代码与promise的then catch)
->dom渲染 ( 如:$().append() )
->新一轮宏任务(如: 定时器 ,dom事件,ajax) //重复前面的流程循环
//js是单线程的,而且和dom渲染共用一个线程
深入理解: (加深印象)
call stack : 调用栈,all代码无论是同步还是异步都会先进入调用栈,然后再决定下一步
Browser console : 浏览器控制台,打印输出结果
web Apis : 处理浏览器提供的api
Micro task queue : 微任务队列
Callback queue : 回调队列,存放宏任务
Event loop : 事件轮询,在dom渲染结束后,不断旋转,检查回调队列中是否有任务,有则执行下一轮宏任务
以后面提供的实例为例:
-
all代码从上到下,进入调用栈:
同步的,立即执行,在控制台输出打印结果
微任务,进入微任务队列(micro task queue)
宏任务,移交给web APIs处理,触发后(如,定时器设定的时间到了),web Apis将其移到回调队列(callback queue) -
记住,all代码都不会在调用栈做过多的停留,当all代码都在调用栈过了一遍后,这时候调用栈就立马空了,查看微任务队列是否有任务,有的话将其all微任务执行完;微任务队列空了后,执行dom渲染;渲染结束启动event loop,检查回调队列中是否有任务,有则开启下一轮宏任务;
-
为什么事件轮询是循环的?
因为宏任务是先交给浏览器处理,触发后,浏览器才将其移入宏任务队列,所以,even loop需要不断反复检查回调队列.
实例
async function fn1 () {
//!!!await 行及前面的代码都是同步
console.log('async1 start')
await fn2()
//!!!await行后的代码:异步,微任务
console.log('async1 end')
}
async function fn2 () {
console.log('async2 ')
}
console.log('第1轮宏任务 start,执行all同步代码')
fn1()
setTimeout(() => console.log('第2轮宏任务'),1000)
new Promise((res, rej) => {
console.log('promise start')
res("promise then")
}).then(e => console.log(e))
console.log('第1轮宏任务 end,执行第1轮微任务')
答案:
第1轮宏任务 start,执行all同步代码
async1 start
async2
promise start
第1轮宏任务 end,执行第1轮微任务
async1 end
promise then
第2轮宏任务
做题重点:
- Promise构造函数的实参本身是同步的,Promise的then和catch是异步的;
- 异步函数本身是同步的,await行后面的代码才是异步执行的
菜鸟一只,有不对的地方欢迎指正 . ☺
若有哪里没写明白,欢迎询问,会尽早回答. ☺