首页 > 其他分享 >事件循环机制

事件循环机制

时间:2024-10-18 22:00:46浏览次数:5  
标签:console log 队列 任务 循环 线程 事件 机制 执行

1.同步/异步

JS是单线程的 只能同步执行代码 比如:

console.log(1);
console.log(2);
conosle.log(3);
输出:1 2 3

以下代码会输出2、3、1,像这种不按顺序执行的,或者说代码执行中间有时间间隙的,叫异步。

setTimeout(() => {
    console.log(1);
}, 0);
console.log(2);
conosle.log(3);
输出:2 3 1

但是浏览器是多线程的,一个浏览器通常有以下几个常驻的线程:
1.渲染引擎线程:该线程负责页面的渲染
2.JS引擎线程:负责JS的解析和执行
3.定时触发器线程:处理定时事件,比如setTimeout, setInterval
4.事件触发线程:处理DOM事件
5.异步http请求线程:处理http请求

渲染线程和JS引擎线程是不能同时进行的。也就是说在执行代码时,渲染会挂起;渲染DOM时,代码也不会执行。 虽然JS是单线程,但是浏览器是多线程的,在遇到像setTimeout、DOM事件、ajax等这种任务时,会转交给浏览器的其他工作线程(上面提到的几个线程)执行,执行完之后将回调函数放入到任务队列。

// eventLoop是一个用作队列的数组
// (先进,先出)
var eventLoop = [ ];
var event;
// “永远”执行
while (true) {
    // 一次tick
    if (eventLoop.length > 0) {
        // 拿到队列中的下一个事件
        event = eventLoop.shift();
        // 现在,执行下一个事件
        event();
    }
}

我们可以用上面的代码来想像一下JS的执行情况。
JS主线程,就像是一个while循环,会一直执行下去。在这期间,每次都会查看任务队列有没有需要执行的任务(回调函数)。在执行完一个任务之后, 会继续下一个循环,直到任务队列所有任务都执行完为止。

1.微任务/宏任务

任务队列又分微任务队列和宏任务队列

微任务

Promise
MutationObserver(Mutation Observer API 用来监视 DOM 变动)
Object.observe()(已废弃)

宏任务

setTimeout
setInterval
setImmediate
I\O
UI rendering(DOM event)

执行过程
在JS执行完同步任务之后,会开始执行微任务队列
在将所有的微任务执行完之后,会开始执行宏任务队列
在执行完一个宏任务之后,跳出来,重新开始下一个循环(从1开始执行)

也就是说执行微任务队列 会将队列中的所有微任务执行完 而执行宏任务队列 每次只执行一个宏任务 然后重新开始下一个循环 我们可以看看以下代码

setTimeout(() => {
    console.log(3)
    new Promise((resolve, reject) => {
        console.log(5)
        resolve()
    }).then(console.log(6))
}, 0)

setTimeout(() => {
    console.log(4)
}, 0)

new Promise((resolve, reject) => {
    console.log(1)
    resolve()
}).then(console.log(2))

输出是1 2 3 5 6 4

我们来分析一下代码的执行过程

前面的两个setTimeout都是宏任务,所以现在宏任务队列有2个任务
Promise里面的代码是同步任务,所以现在会马上执行 输出1
Promise的then是微任务,所以现在微任务队列有1个任务
在执行完同步任务之后,开始执行微任务,也就是console.log(2), 输出2
在执行完微任务之后,会执行宏任务,第一个宏任务也就是第一个setTimeout
第一个setTimeout会先输出3,然后输出5,因为这两个都是同步任务,然后遇到then,加入微任务队列,宏任务执行完重新开始下一个循环。
因为没有同步代码,所以接着执行微任务,此时微任务队列有1个任务(第6步加入), 宏任务队列还有1个任务(第6步执行完了第一个宏任务)
执行微任务,输出6
再执行宏任务,输出4

标签:console,log,队列,任务,循环,线程,事件,机制,执行
From: https://www.cnblogs.com/xiaohanga/p/18475107

相关文章

  • Java中的反射机制,如何应用反射?
    目录1.类比“万能钥匙”来理解反射机制2.反射机制的优点有哪些?3.代码示例4.扩展知识5.反射的性能考虑        Java的反射机制是指在运行时获取类的结构信息(如方法、字段、构造函数),并操作对象的一种机制。反射机制提供了在运行时动态创建对象、调用方法、......
  • 第9篇:网络访问控制与认证机制
    目录引言9.1访问控制策略概述9.2认证机制的使用9.3密钥分发与证书机制9.4访问控制与认证在网络安全中的应用9.5网络访问控制与认证的挑战9.6总结第9篇:网络访问控制与认证机制引言随着计算机网络的不断普及,安全问题日益受到关注。网络访问控制和认证机制是确......
  • 双亲委派机制以及类加载过程就是这样啊
    类加载过程:简洁来说就是将我们的已经完成编译的class字节码文件通过类加载器到我们JVM的内存运行时数据区成为我们可以在程序中可以使用的class对象,而类加载器就是通过双亲委派机制来实现的,这个也是反射的底层实现的原因具体流程: 加载链接 初始化加载:就是通过类加......
  • Spring中的事务提交事件
    如果想在spring操作事务结束后执行一些代码,应该怎么办?为什么要这样?比如我们在事务中给其他系统发了消息,期望事务提交后过一会收到这个系统的回应,然后操作刚刚提交的数据。但是如果回应来的太快就像龙卷风,我们的事务是托管给Spring的可能还没提交,也就没法操作了一个方案是使用......
  • DiffSinger: 基于浅层扩散机制的歌声合成新技术
    DiffSingerDiffSinger:开创歌声合成新纪元在人工智能和深度学习技术飞速发展的今天,计算机生成的歌声越来越接近真人歌唱。而在众多歌声合成技术中,DiffSinger无疑是一颗冉冉升起的新星。这项由刘景林等人在2021年提出的技术,正在为歌声合成领域带来革命性的变革。DiffSinger的......
  • 动态事件id反查事件类型
    简介项目中的事件派发系统,会动态生成唯一id并赋值给对应字段,当发生报错时,日志仅打印事件id,并不知道具体事件类型,故作此拓展。方案思路构建一个新的特性,将使用有事件id的类全部使用此特性注册一次获取到所有程序集,并将注册过此特性的类全部持有到在初始化时,将所有事件id记......
  • windows日志怎么查看(含windows事件ID状态码)
    要查看Windows异常重启日志,可以按照以下步骤进行操作:打开“事件查看器”:在Windows操作系统中,按下Win+R键,在运行对话框中输入“eventvwr.msc”,然后点击“确定”按钮。在“事件查看器”窗口中,展开“Windows日志”文件夹,然后选择“系统”。在右边的窗格中,你会看到所有系统......
  • js 中断循环的几种方式
    在JavaScript中,`forEach`方法是用来遍历数组的元素,并且它不能被中断或退出。如果你需要在满足某个条件时中断循环,你可以考虑使用其他循环结构,比如`for`循环、`for...of`循环或者`while`循环。下面是一些替代方案:1.**使用`for`循环**:```javascriptletarray=......
  • TPAMI 2024 | 具有识别机制的可扩展视频目标分割
    题目:ScalableVideoObjectSegmentationWithIdentificationMechanism具有识别机制的可扩展视频目标分割作者:ZongxinYang;JiaxuMiao;YunchaoWei;WenguanWang;XiaohanWang;YiYang摘要本文探讨了在半监督视频目标分割(VOS)中实现可扩展和有效的多目标建模所......
  • Nuxt.js 应用中的 app:templates 事件钩子详解
    title:Nuxt.js应用中的app:templates事件钩子详解date:2024/10/18updated:2024/10/18author:cmdragonexcerpt:app:templates是Nuxt.js中一个强大的生命周期钩子,它在NuxtApp生成过程中调用。这一钩子允许开发者自定义、修改或添加新文件到构建目录,提供了极大的......