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

js的事件循环机制的理解

首先,我们要理解JavaScript是一门单线程的语言。所谓单线程,简单来说一个时间只能做一件事,只有做完这件事,才能进行下一件。那为什么选择单线程,不选择多线程呢?这是由JS的用途决定的,JS的用途是与用户交互,以及操作DOM,假设JS有两个线程,一个要在某个DOM节点上添加内容,一个要删除这个节点,那浏览器该以哪个为准呢,事情就变得复杂了。因此,JS在诞生时就是单线程,以后也不会改变。

这个时候就出现了问题,如果一件任务耗时太长,就会阻塞后面的任务。这样肯定是不行的,所以,JS设计者将任务分成同步任务和异步任务。

同步任务就是在主线程(调用栈 Call Stack)中按照书写顺序依次执行的任务。异步任务就是不阻塞主线程,而是交由其他线程或系统处理(如浏览器 或 Node.js ),处理完毕后,将其回调函数推入任务队列。等到主线程空了,任务队列中的任务再根据FIFO算法被调度到主线程中执行。

事件循环的工作流程如下:

1.执行调用栈中的所有同步代码,直到栈空。【栈是后进先出结构,但是同步代码入栈后直接执行,执行完毕弹出,所以顺序还是不变的,但如果函数嵌套,则调用栈可能存在多层函数上下文,最后进入的上下文最先执行完,所以最先弹出】
2.检查任务队列,依次将任务调度到调用栈中执行,直到队列空。
3.重复循环。

只要调用栈空了,就去任务队列中读取任务,【用户点击按钮触发函数,函数就会被推入调用栈执行】这个过程不断重复循环,这就是JavaScript的运行机制, 这种机制就叫做事件循环机制

所以有一个小细节就是setTimeout(callback,s)的真正含义并不是在指定的毫秒数后调用函数,而是最快s毫秒后调用函数,因为它需要等待主线程空后再被调用。

但是这里面还有更细节的问题,在事件循环的早期设计中,所有异步任务都进入同一个任务队列。但随着前端复杂度提升,任务优先级问题显露出来:

紧急任务需要优先处理(如 Promise 状态更新)
非紧急任务可以延后(如 UI 渲染前的计算)

因此,现代事件循环又将异步任务细分为两类:
在这里插入图片描述
同步任务与宏任务:整个脚本(主线程代码),即script标签里的代码,本身就是一个宏任务,主线程执行脚本中的同步代码属于初始宏任务。整个脚本的执行是第一个宏任务,同步代码是它的组成部分。

于是,事件循环的工作流程就变成:

1.按照代码书写顺序执行初始宏任务:
如果遇到同步代码,直接推入调用栈执行。
如果遇到宏任务,将回调函数推入宏任务队列。
如果遇到微任务,将回调函数推入微任务队列。

2.清空微任务队列:
当前宏任务执行完毕后,依次将微任务队列中的所有微任务推入调用栈执行,直到微任务队列清空。
注意:若微任务中又生成新的微任务,新微任务也会在此阶段被立即执行。

3.渲染更新(如有必要):
浏览器判断是否需要渲染(通常根据屏幕刷新率,如 60Hz 对应约 16.6ms/次)。

4.开启下一轮事件循环:

从宏任务队列中取出下一个宏任务执行,重复上述流程。

Tips:我的一些思路历程
刚开始我以为js在遇到settimeout这种定时器时,会将整个定时器函数推到宏任务队列中,但其实不是的,
【如果是这样的话,那一个3秒的宏任务,会和一个耗费8秒的微任务几乎同时分别推入宏任务队列和微任务队列,那这个时候如果调用栈执行空了,先取出这个微任务执行,那可能8s的打印出来了,定时器还没打印出来,这个深究的话这个理解是错误的,不过可以帮我记住任务队列里放的都是处理过的回调
js遇到定时器之后,将定时器以及回调交给浏览器,由浏览器的定时模块发起定时,处理完毕后(例如三秒后)将回调函数推入宏任务队列。

接着列举一些宏任务和微任务的理解,以及他们是怎么分类的
宏任务:
由宿主环境发起,比如浏览器或者Node。js遇到这些任务时会向对应的环境发起请求,由浏览器或者node进行处理,处理完毕后推入宏任务队列

‌浏览器环境‌: setTimeout、setInterval【定时器触发线程】、DOM事件【事件触发线程、GUI渲染线程】、AJAX回调【浏览器网络线程】等需要浏览器线程协作的任务
‌Node环境‌: I/O操作、setImmediate等系统级异步操作

微任务:
由JavaScript引擎自身发起和管理【相当于是一种js本身的异步机制】,例如js遇到promise的时候,会执行promise的同步部分,然后将promise的状态标记为pending,而直到当resolve/reject被调用时,js才会将对应的.then或者.catch回调函数推入微任务队列

‌语言级实现‌:Promise.then/catch/finally、queueMicrotask等属于ECMAScript规范定义的异步机制


文章转载自:

http://cDYELjoi.hxxwq.cn
http://Wfa8DkLD.hxxwq.cn
http://3AXoFIpb.hxxwq.cn
http://5yZ4vaY1.hxxwq.cn
http://V62TfJSO.hxxwq.cn
http://oYU099Uc.hxxwq.cn
http://jWbLWxLv.hxxwq.cn
http://YIvEFDmW.hxxwq.cn
http://AVBO6v91.hxxwq.cn
http://QUVfe3Ag.hxxwq.cn
http://kfvmwBgn.hxxwq.cn
http://43tBNFFH.hxxwq.cn
http://IWOYw1AP.hxxwq.cn
http://nhCLcXte.hxxwq.cn
http://H2YWjDQD.hxxwq.cn
http://rjNo9kiv.hxxwq.cn
http://PPdIEaWj.hxxwq.cn
http://gak6byGg.hxxwq.cn
http://vFQcA8xQ.hxxwq.cn
http://7DlJHwrb.hxxwq.cn
http://gIME7S5i.hxxwq.cn
http://CT1BgUC8.hxxwq.cn
http://JPdJYgcp.hxxwq.cn
http://sEYXodlL.hxxwq.cn
http://tCnLnFVg.hxxwq.cn
http://ySUF6MCq.hxxwq.cn
http://pODAQzYm.hxxwq.cn
http://RNTqgSUh.hxxwq.cn
http://goxjK5N9.hxxwq.cn
http://4L3mA9sX.hxxwq.cn
http://www.dtcms.com/a/378944.html

相关文章:

  • MATLAB基于博弈论-云模型的城市道路塌陷风险评价模型
  • 医保购药平台如何对接互联网医院系统源码?技术难点与解决方案
  • 景观设计师的数字画笔:园林景观设计软件有哪些
  • 配置docker常见问题
  • 华宇TAS应用中间件与瀚高股份两款产品完成兼容互认证
  • 详解 C++11
  • GS1-128 校验码计算方法
  • UnityShader:正反面显示不同颜色
  • c++打包pyd文件给Python使用调用函数
  • 设计模式-适配器备忘录组合迭代器
  • Linux上解决telnet失败问题
  • xtuner安装及微调大模型
  • FlexSPI 传输结构体解析
  • 简单的GIT操作学习记录
  • K8S的dashboard部署与访问
  • css之一个元素可以同时应用多个动画效果
  • STM32之水质浑浊度传感器模块
  • 【Qt】【C++】虚析构函数及 virtual ~Base() = default
  • 马斯克访谈深度解读:机器人、AI芯片与人类文明的未来
  • 深入理解 CMake 脚本片段:文件查找、字符串替换与条件处理
  • Google Ads广告验证全攻略:如何借助动态住宅IP精准投放?
  • Linux防火墙配置指南:限制特定IP访问并允许其他所有流量
  • 使用动态IP 需要注意什么
  • 2025年- H128-Lc205. 同构字符串(哈希表)--Java版
  • 今天我们开始学习iptables防火墙
  • Android逆向学习(十一) IDA动态调试Android so文件
  • 第二篇:排序算法的简单认识【数据结构入门】
  • 嵌入式铁头山羊stm32:一文总结
  • HDFS(Hadoop 分布式文件系统)知识点梳理
  • AI幻觉的罪魁祸首