JavaScript异步编程——12-事件循环机制、宏任务和微任务【万字长文,感谢支持】

浏览器的事件循环机制(重要)

image-20230608154453933

执行顺序如下:

  • 同步任务:进入主线程后,立即执行。

  • 异步任务:会先进入 Event Table;等时间到了之后,再进入 任务队列 (Event Queue)排队(排队是因为同一时间,JS 只能执行一个任务),先进先出。比如说,setTimeout(()=> {}, 1000)这种定时器任务,需要等一秒之后再进入 Event Queue。

  • 当主线程的任务执行完毕之后,此时主线程处于空闲状态,于是会去读取 Event Queue 中的任务队列,如果有任务,则进入到主线程去执行。

Node.js 事件循环机制

浏览器的 EventLoop 依据的是 HTML5 规范。而 Node.js 的 EventLoop 是由Node.js底层的 libuv 规定的。 libuv是一个专注于异步IO的跨平台库。

Node.js的事件循环中,有六个队列。其中,微任务有两个队列,宏任务有四个队列。

一、微任务队列:

  • 顺序1:next tick queue。比如:process.nextTick

  • 顺序2:other queue。比如:Promise的then回调、queueMicrotask

二、宏任务队列:

  • 顺序3:timer queue。比如:setTimeout、setInterval

  • 顺序4:poll queue。比如:IO事件

  • 顺序5:check queue。比如:setImmediate

  • 顺序6:close queue。比如:close事件

参考链接:

宏任务和微任务

JS中的任务分为同步任务、异步任务。

JS中的异步任务分为宏任务(macrotask)、微任务(microtask)。在早期,异步任务中只有宏任务,没有微任务。后来的语言标准中,推出了“微任务”,因为希望微任务能够尽早执行

宏任务、微任务分类

事件循环的队列中,有两个队列。

1、宏任务队列,包含这些任务:

  • ajax 网络请求

  • setTimeout、setInterval

  • DOM事件

  • UI渲染

  • I/O文件读写操作。

2、微任务队列,包含这些任务:

  • Promise的then回调

  • Mutation Observer API:监听DOM节点变化。

  • queueMicrotask():可直接将某个任务加入到微任务队列中。

在执行一个 Promise 对象时,当走完 resolve() 进入 fulfilled状态后,会立刻把 .then()里面的代码加入到微任务队列当中。

任务的执行顺序

JS中的任务执行顺序:同步任务 --> 微任务 --> 宏任务

在执行任何一个宏任务之前(不是队列,是一个宏任务),都会先查询微任务队列中是否还有任务需要执行

  • 当前宏任务执行之前,必须要保证微任务队列是空的。

  • 如果微任务队列不为空,那就优先执行微任务队列中的任务。

任务执行顺序的面试题

实际开发中,基本不会出现下面这些题目,因为很多时候我们无法精准控制异步任务的执行顺序。但是它们在面试中出现的频率特别高,因为熟悉这些思维训练,有利于考察我们对JS单线程、事件循环机制、宏任务和微任务等原理的掌握程度。

题 1:宏任务和微任务的执行顺序

 setTimeout(() => {
   // 宏任务
   console.log('setTimeout');
 }, 0);
 ​
 new Promise((resolve, reject) => {
   resolve();
   console.log('promise1'); // 同步任务
 }).then((res) => {
   // 微任务
   console.log('promise then');
 });
 ​
 console.log('同步任务'); // 同步任务

打印结果:

 promise1
 同步任务
 promise then
 setTimeout

上方代码执行的顺序依次是:同步任务 --> 微任务 --> 宏任务

题 2:在宏任务中嵌套了微任务

 new Promise((resolve, reject) => {
   setTimeout(() => {
     resolve();
     console.log('setTimeout'); // 宏任务
   }, 0);
   console.log('promise1');
 }).then((res) => {
   // 微任务
   console.log('promise then');
 });
 ​
 console.log('同步任务');

打印结果:

 promise1
 同步任务
 setTimeout
 promise then

上方代码解释:在执行宏任务的过程中,创建了一个微任务。但是需要先把当前这个宏任务执行完,再去创建并执行微任务。

题3:综合题

 console.log("script start")
 ​
 setTimeout(() => {
   console.log("setTimeout1");
   new Promise(resolve => {
     resolve();
   }).then(() => {
     new Promise(resolve => {
       resolve();
     }).then(() => {
       console.log("then1");
     });
     console.log("then2");
   });
 });
 ​
 new Promise(resolve => {
   // 下面这两行代码,即便调换顺序,也不影响打印结果
   console.log("promise1");
   resolve();
 }).then(() => {
   console.log("then3");
 });
 ​
 setTimeout(() => {
   console.log("setTimeout2");
 });
 ​
 console.log('同步代码');
 ​
 queueMicrotask(() => {
   console.log("queueMicrotask")
 });
 ​
 new Promise(resolve => {
   resolve();
 }).then(() => {
   console.log("then4");
 });
 ​
 console.log("script end");
打印结果:

 // 第一次循环
 script start
 promise1
 同步代码
 script end
 ​
 // 第二次循环
 then3
 queueMicrotask
 then4
 ​
 // 第三次循环
 setTimeout1
 then2
 then1
 ​
 // 第四次循环
 setTimeout2

题4:async await 题目

代码举例:

 console.log('script start')
 ​
 async function async2() {
   console.log('async2')
 }
 ​
 async function async1() {
   console.log('async1 start')
   await async2();
   console.log('async1 end')
 }
 ​
 setTimeout(() => {
   console.log('setTimeout')
 }, 0)
 ​
 async1();
 ​
 new Promise(resolve => {
   console.log('promise1')
   resolve();
 }).then(function () {
   console.log('then1')
 })
 ​
 console.log('script end');

打印结果:

 script start
 async1 start
 async2
 promise1
 script end
 ​
 async1 end
 then1
 ​
 setTimeout

希望各位可以点个赞点个关注,这对up真的很重要,谢谢大家啦!

  • 27
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
MySQL多数据源是指在一个应用程序中同时使用多个不同的MySQL数据库来存储和管理数据的技术。它可以帮助开发人员更灵活地处理各种数据库操作,提高程序的性能和可扩展性。下面是一个完整的MySQL多数据源教程。 一、设置数据库连接信息 1. 在应用程序的配置件中,创建多个数据库连接的配置项。例如,可以为每个数据源创建一个配置项,分别命名为db1、db2等。 2. 在配置项中,设置每个数据源的连接信息,包括数据库地址、用户名、密码等。 二、创建数据源管理器 1. 创建一个数据源管理器类,用于管理多个数据源。该类需要实现数据源的动态切换和获取。 2. 使用Java的线程安全的数据结构,如ConcurrentHashMap来存储数据源信息。将配置件中的数据库连接信息加载到数据结构中。 3. 实现方法来切换不同的数据源,通过传入数据源的名称来切换到对应的数据库。 三、实现数据源切换 1. 在应用程序中,根据业务需求选择需要使用的数据源。可以通过调用数据源管理器的方法来切换数据源。 2. 在DAO层的代码中,根据当前使用的数据源名称,选择对应的数据源进行数据库操作。 四、使用多数据源进行数据库操作 1. 在DAO层的代码中,区分不同的数据源,并将数据库操作的代码包装在对应的数据源中。 2. 在业务层的代码中,调用DAO层的方法来进行数据库操作。不同的数据源会自动切换。 五、处理事务 1. 如果需要在一个事务中操作多个数据源,可以使用分布式事务的方式来处理。 2. 可以使用开源的分布式事务框架,如Atomikos、Bitronix等来实现多数据源的事务管理。 六、监控和维护 1. 使用监控工具来监控多个数据源的使用情况,包括连接数、查询次数等。 2. 定期对数据库进行维护,包括索引优化、数据清理等工作,以保证数据库的性能和稳定性。 通过以上步骤,我们可以实现MySQL多数据源的配置和使用。使用多数据源可以更好地管理和处理不同的数据库操作,在提高程序性能和可扩展性的同时,也提供了更灵活的数据操作方式。同时,需要注意合理选择和配置数据源,以及监控和维护数据库,以保证系统的运行效率和数据的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

被瞧不起的神

谢谢啦,感谢支持|一起努力!

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

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

打赏作者

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

抵扣说明:

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

余额充值