js event loop事件队列详解(浏览器中)

本文详细阐述了JavaScript单线程模型,介绍了调用栈、宏队列和微队列的作用,并通过实例解析了异步任务如何在队列中调度。重点讲解了setTimeout, Promise等任务的分配,以及复杂情况下任务执行顺序的变化。
摘要由CSDN通过智能技术生成


前言


以下内容是js在浏览器中的事件队列执行,与在nodejs中有所区别,请注意。

js是单线程的


要知道js是单线程的,就是一件一件做,做完一件做下一件。

认识一个栈两个队列


一个调用栈Stack。
一个宏队列,macrotask,也叫tasks。
一个微队列,microtask,也叫jobs。

执行过程


js就是执行全局Script同步代码,这中间碰到一些异步任务先加进对应的队列。

做完之后,调用栈就为空了。

然后将队列(先微队列后宏队列)里面的首个任务提到调用栈来做,一件一件做完直到队列中的任务都做完。

总结就是,先做同步的任务,再做微队列的任务,再做宏队列的任务。

异步任务怎么分配


这些异步任务包括但不限于:

以下分配给宏队列

setTimeout
setInterval
requestAnimationFrame
I/O
UI rendering

以下分配给微队列

Promise
Object.observe
MutationObserver

常见的宏队列:setTimeout,常见的微队列:Promise

简单例子


    console.log("同步任务1");

    setTimeout(() => {
      console.log("宏任务");
    });

    new Promise((resolve, reject) => {
      console.log("同步任务2");
      resolve("微任务");
    }).then((data) => {
      console.log(data);
    });

    console.log("同步任务3");

结果是(按标号加任务,按箭头执行):

>
在这里插入图片描述

需要注意的是Promise的第一层没有执行回调之前是同步的,也就是上面的同步任务2

难一点的例子


    console.log("同步任务1");

    console.log("同步任务2");

    new Promise((resolve, reject) => {
      console.log("同步任务3");
      setTimeout(() => {
        console.log("宏任务1");
        Promise.resolve()
          .then(() => {
            console.log("微任务5");
          })
          .then(() => {
            console.log("微任务6");
          });
      });
      resolve("微任务1");
    })
      .then((data) => {
        console.log(data);
        return "微任务3";
      })
      .then((data) => {
        console.log(data);
      });

    setTimeout(() => {
      console.log("宏任务2");
    }, 0);

    new Promise((resolve, reject) => {
      resolve("微任务2");
    })
      .then((data, resolve) => {
        console.log(data);
        return "微任务4";
      })
      .then((data) => {
        console.log(data);
      });

    console.log("同步任务4");

如何看呢,先看第一层,红色代表同步,绿色微任务,蓝色宏任务。

我们会把同步任务执行完,然后看见微任务有俩,宏任务也有俩。

本来的执行顺序可能是这样(我这里按照序号来表达顺序了,请和简单例子区分开来):
在这里插入图片描述
但是没那么顺利,执行到标号6时不一样了。

因为微任务执行过程中可能会产生新的微任务

上面的微任务1执行完会把微任务3加在微任务2后面,也就是微任务2执行完也轮不到宏任务,会继续执行新的微任务直到微任务队列暂时为空。

所以接下来会按照加入队列的顺序执行完四个微任务,这时候发现没有新的微任务产生,才开始执行宏任务:
在这里插入图片描述
但是需要注意的是,上面执行到标号5时又不一样了,宏任务一执行后又产生了新的微任务,所以宏任务两个并没有顺利连续执行,而是被插入的微任务拦住了。

要记住微任务与宏任务队列都存在时一定是微任务先执行完再来执行宏任务,即使是宏任务执行产生的微任务也同理
在这里插入图片描述
所以最后的答案,如果存在不理解的,可以在认真回顾一下上文:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在下月亮有何贵干

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值