当前位置: 首页 > news >正文

JavaScript中的事件循环机制

提示:微任务和宏任务是一种过时的说法了,据我所了解,已经没有宏任务的说法了

Js为什么是单线程的?

如果有三个按钮,其回调函数里面处理的代码量用的时间各不相同,用户依次快速的点击三个按钮,此时用户希望的是,先点击的先执行,后点击的后执行,可是由于是Js多线程的,每一个回调函数都会被注册成一个线程,这时,肯定是用时少的先执行。这就造成了一个很大的问题,用户体验很不好

可能有人会问,定时器里的代码为什没有按照顺序执行呢?

答:JavaScript采用了一种排队机制,将异步代码放入了消息队列中,待同步代码执行完后,如果消息队列中存在异步代码需要执行,就会唤醒Js主线程去执行这些异步代码

队列里的代码,谁先放进去,谁先执行。

Event Loop 图解

单线程也是存在着异步和同步的问题。这也正是我们今天的重点内容,事件循环机制(event loop)

先来一张图,感受一下

在这里插入图片描述
代码执行时,肯定是先执行同步代码,再执行异步代码,同步代码执行完后,其代码里定时器的回调函数,Dom事件的回调函数,Ajax请求的回调函数等这些异步代码,会由浏览器WebAPIs管理模块里的对应模块相应管理。当这些回调函数,到达要执行的条件(比如定时器到时间了,用户点击了),会由相应的模块送到队列里,然后执行。

先来看一段代码

setTimeout(() => {console.log('3')
},0)Promise.resolve(2).then(value => console.log(value)
)console.log('1')

控制台打印 1 2 3

你可能会很奇怪,定时器的第二个参数是0,即立马放进了队列里,Promise也是立马达到了满足条件。也会放进队列里,又根据代码的先后执行顺序,队列里肯定先放定时器的回调函数,再放Promise的回调函数,等同步代码执行完后,异步代码就是先执行定时器里回调函数,再执行Promise里的回调函数。控制台输出应该是1 3 2 才对啊!!!可是为啥是 1 2 3 呢?

这就引出了我们今天所学的第二个重点内容?宏任务与微任务

宏任务与微任务

其实,我们的上图是没有画完整的,下面来一张完整图,大家来感受一下

在这里插入图片描述

我们可以看出,队列里又进行了划分,又分为宏队列微队列

宏队列里放的是宏任务

微队列里放的是微任务

(注意:上图的标注的分线程是浏览器的,不是我们的Js代码的。我们只是写的代码交给了浏览器管理)

其Promise和Mutation(vue里会遇到mutation)里的回调函数,会放进微对列里

微队列优先级是高于宏队列优先级,所以上述代码,输出 1 2 3就有理可寻啦

我们通过几个小题练习一下

setTimeout(() => {console.log('4')
},0)setTimeout(() => {console.log('5')
},0)Promise.resolve(2).then(value => console.log(value)
)Promise.resolve(3).then(value => console.log(value)
)console.log('1')//控制打印: 1 2 3 4 5
setTimeout(() => {console.log('4')
},0)Promise.resolve(2).then(value => console.log(value)
)Promise.resolve(3).then(value => console.log(value)
)console.log('1')//控制打印: 1 2 3 4

学到这里,你可能觉得已经结束了,其实并不,还有一个很重要的知识点没讲呢,我们接着学习

setTimeout(() => {console.log('4')
},0)setTimeout(() => {console.log('5')
},0)Promise.resolve(2).then(value => console.log(value)
)Promise.resolve(3).then(value => console.log(value)
)console.log('1')//控制打印: 1 2 3 4 5
setTimeout(() => {console.log('4')Promise.resolve(3).then(value => console.log(value))
},0)setTimeout(() => {console.log('5')
},0)Promise.resolve(2).then(value => console.log(value)
)console.log('1')

控制台打印1 2 4 3 5

别急,这里先给出结论:每执行一个宏任务时,都会检查微队列中是否有待执行的的回调,优先执行微任务

所以打印4后,将输出3的回调放进了微队列中,宏队列在执行输出5的回调函数前,先把微队列给清空了

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Google ghOSt 调度器分析(1)
  • Java语言程序设计 第九章:三个修饰符
  • 【设计模式】行为型设计模式之 策略模式学习实践
  • 【Vue】图形验证码功能
  • python类中常见的内置函数
  • 表的设计与查询
  • 豆瓣电影信息爬虫实战-2024年6月
  • 《Navi日语社》App:日语学习与翻译的智能助手,支持日文OCR识别提取文字,无需打字对着说话就能翻译的日语语音翻译工具!
  • 华为od-C卷100分题目-3用连续自然数之和来表达整数
  • Word中插入Mathtype右编号,调整公式与编号的位置
  • PHP维吾尔文转换成拉丁文
  • 前端JS必用工具【js-tool-big-box】学习,获取当前浏览器向上滚动还是向下滚动,获取当前距离顶部和底部的距离
  • vue-$set修改深层对象的值
  • 【云原生进阶之数据库技术】第二章-Oracle-原理-4.6.3.7-闪回事务查询技术
  • 我用香橙派做了一个Klipper 3D打印控制器
  • 网络传输文件的问题
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 0x05 Python数据分析,Anaconda八斩刀
  • CentOS7 安装JDK
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • Effective Java 笔记(一)
  • MySQL的数据类型
  • npx命令介绍
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • React-Native - 收藏集 - 掘金
  • ReactNativeweexDeviceOne对比
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 好的网址,关于.net 4.0 ,vs 2010
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • (03)光刻——半导体电路的绘制
  • (1)STL算法之遍历容器
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (Matlab)使用竞争神经网络实现数据聚类
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (ZT)一个美国文科博士的YardLife
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (二)c52学习之旅-简单了解单片机
  • (附源码)计算机毕业设计ssm电影分享网站
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (六)Hibernate的二级缓存
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (转)EXC_BREAKPOINT僵尸错误
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET 服务 ServiceController
  • .Net 路由处理厉害了
  • .net 使用ajax控件后如何调用前端脚本
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .php文件都打不开,打不开php文件怎么办
  • /3GB和/USERVA开关
  • @antv/x6 利用interacting方法来设置禁止结点移动的方法实现。
  • @component注解的分类