event loop,microtask macrotask
Posted huangxingyuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了event loop,microtask macrotask相关的知识,希望对你有一定的参考价值。
宏任务,微任务区别
简单说就是优先级的问题,微任务优先级高于宏任务
- 宏任务
setTimeout setInterval I/O UI render <script>
- 微任务
Promise process.nextTick
为什么说微任务优先级高于宏任务?
探索二者执行方式不同原因?
- 执行方式区别
在任务队列中,每一次事件循环,宏任务只提取一个,而微任务会一直提取
每次宏任务消费完以后,就会去消费微任务,将他一次性消费完
- 一个完整的事件循环
初始:
调用栈空
微任务队列空
宏任务有且只有一个script脚本(整体代码)
执行脚本,遇到异步任务,将其放入相应的事件队列中,同步代码执行
同步代码执行完成,macro-task出队
然后micro-task入栈,一次全部执行完
上述过程往复循环,直到队列都清空
- 由此思考,异步更新问题
事件循环:
macroTask-mincroTask-render(不断循环)
所以我们异步更新Dom放在mincroTask更好
比如放在宏任中
setTimeout(task,0)
script同步脚本---> mincrotTask--render--macroTask-mincroTask-render
这样第一次的render无效并没有更新Dom,浪费一次render
- 题目测试
setTimeout(()=>{
console.log('A');
},0);
var obj={
func:function () {
setTimeout(function () {
console.log('B')
},0);
return new Promise(function (resolve) {
console.log('C');
resolve();
})
}
};
obj.func().then(function () {
console.log('D')
});
console.log('E');
// c e d a b
- 思考,为什么会有异步任务(事件队列)
js是单线程,任务执行要排队,必须执行完一个再执行另一个
遇到耗时任务,线程挂机等待,浪费时间,不利于充分发挥CPU的调度能力
于是将耗时的异步任务,放进任务队列中,等同步代码执行完,再去执行他们
- 简单了解cpu
多核?
物理上有几个CPU核心,双核:2个相对独立的cpu核心单元组
CPU和线程关系?
第一阶段:单核,同一时间,CPU只能执行一个计算
第二阶段:单核,多个任务共享CPU,任务快速切换
第三阶段:多核,CPU-A处理线程A,CPU-B处理线程B
CPU与进程和线程关系?
CPU给每个进程分配时间
进程内部由其代码为线程分配时间
所以进程快速切换,线程快速切换
导致我们以为进程和线程并发执行
QQ和微信同时在运行(进程),而QQ能在发消息的同时受到消息(线程)
- 既然有异步任务,为什么Js设计单线程
假如Js多线程,一个线程删除DOM,一个线程操作Dom,以谁为准?
为了避免复杂性,js是单线程,也是其核心
- H5的web worker允许创建多线程,会导致Dom的不受控吗?
不会,因为他创建的子线程完全受控,不得操作Dom,所以并没有改变单线程的本质
- 关于题目注意点
setTimeout(A,500)是在500ms过后才将事件放入宏任务中
setTimeout(A,500)
setTimeout(B,30)
宏任务事件队列[B,A]
而宏任务是按照先入先出的原则,所以B先执行
- 拓展setTimeout不按时执行
事件执行的完整流程是:
执行栈执行完以后(耗时A),然后执行微任务(耗时B),然后去执行宏任务中的事件队列
如果A+B > 500,就会出现setTimeout不按时执行
注意异步任务
异步事件会先进入Event Table并注册为函数
当指定的事情完成以后,才会将函数移入事件队列中
所以其实事件队列中就是等待被执行的回调函数
鼠标点击,页面滚动,指定的回调函数,
以上是关于event loop,microtask macrotask的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript Event Loop 机制详解与 Vue.js 中实践应用
DeprecationWarning: There is no current event loop loop = asyncio.get_event_loop()
DeprecationWarning: There is no current event loop loop = asyncio.get_event_loop()