eventLoop 宏任务与微任务与消息队列

先看一道题
在这里插入图片描述

这个就涉及到JavaScript事件轮询中的宏任务和微任务。那么,你能说清楚到底宏任务和微任务是什么?是谁发起的?为什么微任务的执行要先于宏任务呢?
在这里插入图片描述

如上图所示,其中MessageQueue也叫taskQueue,MicrotaskQueue也叫jobsQueue.
定时器,xhr,各种dom事件(点击。。)等异步放到消息队列,promise等放到微任务里面。宏任务与微任务我们放到后面说

现在我们来看开头那道题的执行过程
在这里插入图片描述
可以看到执行先后顺序为 调用栈 > 微任务 > 消息队列。
每次执行消息队列中的任务前都会检查微任务队列吗?

如果消息队列中有task1和task2,当执行完task1过程中,微任务队列加入了一个task3,那么下一步是执行task2还是执行task3呢?如果先执行task3,那么说明再执行每个消息队列中的任务前都会先检查其它任务队列,先执行优先级高的任务队列中的任务。

var promise_task = new Promise((resolve,reject) => {
	resolve('task3');
});
var resolve_callback = (resolve_message) => {console.log(resolve_message)}
var message_task1 = () => {
	promise_task.then(resolve_callback);
	console.log('task1');
}
var message_task2 = () => {console.log('task2');}
setTimeout(message_task1,0);
setTimeout(message_task2,0);
 
 
//result:
//task1
//task3
//task2

事实证明js在每次执行消息队列中的任务前都会检查其它任务队列(至少会检查微任务队列),根据队列优先级决定先执行哪个队列中的任务。

调用栈呢?

那么每次在检查消息队列前会不会检查调用栈?
这个问题我觉得会,不仅消息队列前会,微任务队列前也会,因为这两个队列都是将代码放入调用栈中执行,所有无论什么时候在调用栈中加入代码(stop),下一步无论原本该执行消息队列还是微任务队列都会变成执行(stop)。

我们声明一个promise和一个message_task函数。在这个promise的回调函数中使用setTimeout创建一个message_task的消息队列任务,同时在message_task中调用promise.then 函数创建一个微任务队列任务。这样两个任务会循环创建并循环执行,之后在执行过程中我们在控制台执行alert(‘stop’),看是是否会立即出现弹窗

var promise_task = new Promise((resolve,reject) => {
	resolve('j_task');
});
var resolve_callback = (resolve_message) => {
	setTimeout(message_task,0);
	console.log(resolve_message);
}
var message_task = () => {
	promise_task.then(resolve_callback);
	console.log('m_task');
}
 
promise_task.then(resolve_callback);
 
 
//result:
//console会循环打印 j_task 和 m_task
//这时在console中键入alert('stop')命令,弹出alert框,console中打印暂停

即每次选择执行任务前(或者每次任务结束后),js会根据主任务队列,job queue,message queue的优先级来挑选将要执行下一个任务是哪个。

宏任务与微任务
那么到底什么是宏任务和微任务呢,

每次宏任务结束后都会去执行当前微任务队列,然后再去执行下一个宏任务。

  • 每个script标签是一个宏任务。
	  <script>
        console.log(22)
        Promise.resolve().then(() => {
          console.log(11)
        })
        console.log(44)
      </script>
      <script>
        console.log(33)
        
      </script>
result:
// 22 44 11 33 共执行两个宏任务,即两个script标签
  • 每个定时器是一个宏任务
<script>
setTimeout(() =>{
    Promise.resolve().then(
        console.log(1111),
        Promise.resolve().then(console.log(5555))
        )
    console.log(333)
setTimeout(() =>{
Promise.resolve().then(console.log(2222))
console.log(444)
},0)
},0)
</script>
result: //1 5 3 2 4  两个宏任务,即两个定时器

当然还有就不一一列举了
在这里插入图片描述

//script1
<script>
            var promise_task = new Promise((resolve,reject) => {
                resolve('j_task');
            });
            var resolve_callback = (resolve_message) => {
                setTimeout(message_task,0);
                console.log(resolve_message);
            }
            var message_task = () => {
                promise_task.then(resolve_callback);
                console.log('m_task');
            }
            
            promise_task.then(resolve_callback);
        </script>
        //script2
        <script>
            console.log(333)
            setTimeout(() => {
                console.log(444)
            }, 0);
            // alert('stop')
            console.log(555)
        </script>
        
result:
		j_task
		333
		555
		m_task
		j_task
		444
		m_task
		j_task
		m_task
		j_task
		......

下图分析一下上面结果,截至到下图步骤6,共执行了 script1 script2 两个宏任务。
在这里插入图片描述

结合之前调用栈,消息队列,微任务队列三者的优先级,以及宏任务定义
补充
查资料的过程中发现有一个tick定义,但是我看不懂到底什么才算是一次tick,关于tick每个人说的都不太一样,这个等以后搞懂再说吧。(tick我现在的理解是执行一个宏任务就是一个tick,在tick结束后,下一个tick开始前渲染页面)

在这里插入图片描述

宏任务与微任务
三者优先级

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值