-
宏任务和微任务
2020-09-22 17:51:06宏任务和微任务 微任务:process.nextTick、MutationObserver、Promise.then catch finally 宏任务:I/O、setTimeout、setInterval、setImmediate、requestAnimationFrame 从上面可以看出宏任务和微任务的区别 宏... -
js宏任务和微任务
2021-02-12 22:02:30宏任务和微任务是异步里api的分类; 1.微任务是es提供的api,常用的有: promise实例.then().catch() & 异步函数中await 行后面的代码 ; 2.宏任务是浏览器提供的api ,常用的有 :定时器 & ajax & dom事件; ...是什么
宏任务和微任务是异步里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行后面的代码才是异步执行的
菜鸟一只,有不对的地方欢迎指正 . ☺
若有哪里没写明白,欢迎询问,会尽早回答. ☺ -
-
JS宏任务和微任务
2020-08-07 17:04:51js 宏任务和微任务 js 宏任务和微任务 .宏任务(macrotask)和微任务(microtask) macrotask 和 microtask 表示异步任务的两种分类。 在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 ...js 宏任务和微任务
.宏任务(macrotask )和微任务(microtask )
macrotask 和 microtask 表示异步任务的两种分类。
在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。
掘金上面盗张图记录一下
宏任务和微任务之间的关系
先看个例子
setTimeout(() => { //执行后 回调一个宏事件 console.log('内层宏事件3') }, 0) console.log('外层宏事件1'); new Promise((resolve) => { console.log('外层宏事件2'); resolve() }).then(() => { console.log('微事件1'); }).then(()=>{ console.log('微事件2') })
我们看看打印结果
外层宏事件1 外层宏事件2 微事件1 微事件2 内层宏事件3
• 首先浏览器执行js进入第一个宏任务进入主线程, 遇到 setTimeout 分发到宏任务Event Queue中
• 遇到 console.log() 直接执行 输出 外层宏事件1
• 遇到 Promise, new Promise 直接执行 输出 外层宏事件2
• 执行then 被分发到微任务Event Queue中
•第一轮宏任务执行结束,开始执行微任务 打印 '微事件1' '微事件2'
•第一轮微任务执行完毕,执行第二轮宏事件,打印setTimeout里面内容'内层宏事件3'
宏任务
# 浏览器 Node setTimeout √ √ setInterval √ √ setImmediate x √ requestAnimationFrame √ x 微任务
# 浏览器 Node process.nextTick x √ MutationObserver √ x Promise.then catch finally √ √ 这个例子看懂基本js执行机制就理解了
//主线程直接执行 console.log('1'); //丢到宏事件队列中 setTimeout(function() { console.log('2'); process.nextTick(function() { console.log('3'); }) new Promise(function(resolve) { console.log('4'); resolve(); }).then(function() { console.log('5') }) }) //微事件1 process.nextTick(function() { console.log('6'); }) //主线程直接执行 new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { //微事件2 console.log('8') }) //丢到宏事件队列中 setTimeout(function() { console.log('9'); process.nextTick(function() { console.log('10'); }) new Promise(function(resolve) { console.log('11'); resolve(); }).then(function() { console.log('12') }) })
• 首先浏览器执行js进入第一个宏任务进入主线程, 直接打印console.log('1')
• 遇到 setTimeout 分发到宏任务Event Queue中
• 遇到 process.nextTick 丢到微任务Event Queue中
• 遇到 Promise, new Promise 直接执行 输出 console.log('7');
• 执行then 被分发到微任务Event Queue中
•第一轮宏任务执行结束,开始执行微任务 打印 6,8
•第一轮微任务执行完毕,执行第二轮宏事件,执行setTimeout
•先执行主线程宏任务,在执行微任务,打印'2,4,3,5'
•在执行第二个setTimeout,同理打印 ‘9,11,10,12’
•整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。
以上是在浏览器环境下执行的数据,只作为宏任务和微任务的分析,我在node环境下测试打印出来的顺序为:1,7,6,8,2,4,9,11,3,10,5,12。node环境执行结果和浏览器执行结果不一致的原因是:浏览器的Event loop是在HTML5中定义的规范,而node中则由libuv库实现。libuv库流程大体分为6个阶段:timers,I/O callbacks,idle、prepare,poll,check,close callbacks,和浏览器的microtask,macrotask那一套有区别。
参考文档 https://juejin.im/post/59e85eebf265da430d571f89
http://www.cnblogs.com/jiasm/p/9482443.html
链接:https://www.cnblogs.com/wangziye/p/9566454.html