事件队列,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并注册为函数
当指定的事情完成以后,才会将函数移入事件队列中
所以其实事件队列中就是等待被执行的回调函数

鼠标点击,页面滚动,指定的回调函数,



猜你喜欢

转载自blog.csdn.net/qq1498982270/article/details/89482707