首页 > 其他分享 >事件轮询Event loop

事件轮询Event loop

时间:2022-08-29 17:36:26浏览次数:91  
标签:异步 console log 轮询 任务 代码执行 执行 Event loop

事件轮询(event loop)

含义

event loop即事件轮询,这个是js里面为了解决单线程阻塞问题提出的解决方案,也是js异步执行机制的原理

单线程

  • 众所周知,js执行是单线程的,什么是单线程呢,简单的理解就是玩游戏的时候就一条主线,没有支线任务。
  • 单线程的特点:
    1. 代码执行从上往下执行
    2. 上面代码报错下面代码就会停止执行
  • 单线程的优点:
    • 单线程能够保证代码执行的顺序,比如说dom生成和删除,如果用多线程处理会出现一个线程生成,另一个进程删除,这样可能每一个线程执行的时机出错,还未生成dom这时候就移除dom,导致代码异常报错,所以单线程能够保证程序的稳定性
  • 单线程的缺点:
    • 单线程的缺点就是程序阻塞问题,如果一个任务所用的时间比较长或者无法估计,这样就会导致程序被卡住,导致程序假死,后面的代码就无法得到及时的运行。比如说setTimeout、ajax请求、promise的then方法之类的
  • 解决单线程的问题:
    • js里面提出了同步和异步的代码执行方式

同步和异步

  • 同步执行方式: 同步的执行方式是指代码执行从上往下执行的,上面的代码没有执行结束,下面的代码是会在等待状态,比如说for循环,无论for循环执行多少次,程序都会等待,这样就能够获取循环之后的值。
    console.log(1)
    console.log(2)
    console.log(3)
    let sum = 0
    for(let i=0;i<10000;i++){
        console.log(i)
        sum+=i
    }
    console.log(sum)
  • 异步执行方式:异步的执行方式是指js执行的时候将耗时比较长的或者无法预估的任务丢到另一个队列里面,先执行同步的代码,等同步的代码执行结束,再来处理异步的代码
    console.log(1)
    console.log(2)
    console.log(3)
    setTimeout(() => {
        console.log(4)
    }, 3000);
    console.log(5)
  • 异步的优点:异步的优点能够保证js在处理耗时任务的时候提高程序执行的效率,减少任务等待的时间
  • 异步的缺点:异步的缺点在于如果是一个异步的任务,任务执行完成之后无法通过返回值的方式获取异步任务的结果,需要通过回调函数获取结果
    function foo(){
        var a = 1
        setTimeout(()=>{
            a++
        }, 0)
        return a
    }
    var num = foo()
    console.log(num) // 1
    // 使用回调函数拿到结果
    function foo(baz){
        var a = 1
        setTimeout(()=>{
            a++
            baz(a)
        }, 0)
    }
    foo(function(num){
        console.log(num) // 2
    })
  • 但是异步任务执行的顺序又是怎样的呢?这时候我们就需要了解事件轮询机制
    console.log(1)
    setTimeout(()=>{
        console.log(2)
    },0)
    setInterval(() => {
        console.log(3)
    }, 30);
    console.log(4)
    console.log(5)
    new Promise((resolve)=>{
        console.log(6)
        resolve(7)
    }).then(res=>{
        console.log(res)
    })

事件轮询

  • 图示
  • 图解
    1. 首先加载js的时候,整个的script代码会一行一行的执行
    2. 每一行代码执行都会进入调用栈,调用栈是一个执行代码的地方
    3. 调用栈在运行代码的时候会判断这行代码是同步还是异步,如果是同步直接执行返回执行之后得到的结果,如果是异步,会将异步的代码放到webAPI里面,直接执行后面的同步代码
    4. 异步的代码在webAPI里面会等待时机,比如说一个定时器3s执行,在3s到达的时候会将对应的回调函数添加到执行的队列(task queue)里面
    5. 所有的同步代码执行结束之后,此时会开启事件轮询,查看task queue里面是否有任务需要执行,如果有就拿到调用栈执行,一直到所有的task queue任务结束
  • 案例
console.log(1)
setTimeout(function cb(){
    console.log(2)
}, 1000)
console.log(3)
  • 执行过程
    1. console.log(1)进入调用栈 是同步 控制台打印输出 1 结束
    2. setTimeout(cb, 1000) 进入调用栈 是异步, 将cb放入webAPI等待,继续执行下一步代码
    3. console.log(2)进入调用栈 是同步 控制台打印输出 2 结束
    4. 此时调用栈任务执行结束,开启事件轮询
    5. cb函数在一秒钟后进入执行队列(task queue)
    6. cb函数进入调用栈执行,输出 3 结束
  • 点击查看完整代码执行
  • 总结
    • 可以看出所有的同步任务都会在异步任务之前执行
    • 异步任务如果有很多 他们的执行顺序又是如何呢

宏任务和微任务

  • 宏任务:macrotask,setTimeout,setInterval, ajax, dom事件,宏任务是由浏览器提供的
  • 微任务:microtask,promise,async/await,微任务是由es6提供的
  • 为什么要区分宏任务和微任务?
    • 因为宏任务和微任务的执行时机不一样,这样就会导致我们对于异步的代码认识产生理解的误区
  • 执行顺序
    1. js首先会执行调用栈里面同步的代码
    2. 遇到宏任务,会将宏任务的回调函数压入到webapi中等待,合适进入task queue队列等待
    3. 遇到微任务,会将微任务的回调函数压入micro task queue队列中
    4. 调用栈中所有同步代码执行完成,开启event loop,会优先执行micro task queue队列中的回调函数
    5. 微任务执行完成之后,dom进行渲染
    6. dom渲染完成,会执行task queue中的的回调函数
    7. 重复以上步骤
  • 案例演示
console.log(1)
setTimeout(function cb(){
    console.log(2)
}, 0)
new Promise(function handler(resovle){
    resovle(3)
}).then(function(res){
    console.log(res)
})
console.log(4)

微任务执行在DOM渲染之前执行,宏任务执行在DOM渲染之后

<body>
    <h1>页面中的元素</h1>
    <script>
        console.log(1)
        setTimeout(function cb(){
            alert(222)
            console.log(2)
        }, 1000)
        new Promise(function handler(resovle){
            resovle(3)
        }).then(function(res){
            alert(111)
            console.log(res)
        })
        console.log(4)
    </script>
</body>
</html>
  • 弹出alert(111)的弹窗此时页面上h1并没有生成,弹出alert(222)的时候页面h1已经生成,由此证明微任务是在dom渲染之前执行,宏任务是在dom渲染之后执行

标签:异步,console,log,轮询,任务,代码执行,执行,Event,loop
From: https://www.cnblogs.com/crim/p/16636668.html

相关文章

  • Airtest IDE 自动化测试9——text和keyevent
    前言在AirtestIDE的Airtest录制辅助窗内,包含有三种类型的录制按钮:操作类型辅助类型断言类型touchtextassert_existsswipekeyeventassert_not_exists......
  • C# 事件总线 EventBus(转载)
    原文地址:https://www.cnblogs.com/MuNet/p/8546362.html1.引言事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉。事件总线是对发布-订阅模......
  • 实验4 [bx]和loop的使用
    1.编程,向内存0:200~0:23f依次传送数据0~63(3fh),程序中只能用9条指令,包括movax,4c00h和int21hassumecs:codecodesegment movax,0020h movds,ax movbx,0 ......
  • 五--[BX]和loop指令
    用[0]表示一个内存单元时,0表示偏移地址,段地址默认在ds中,单元的长度(类型)由具体指令中的其他对象指出我们定义的描述性符号:“()”,表示一个寄存器或内存单元中的内容,比如(ax......
  • tauri学习(7)-事件(event)
    接上节继续,今天来研究tauri的事件(event),假设老板提了个需求,希望能实时监控cpu、内存等性能指标,你会怎么做?思路1:后端Rust暴露1个command,前端js不停去轮询(参考前文:tauri......
  • vue——全局事件总线(GlobalEventBus)
    一.什么是全局事件总线?1.一种组件间通信的方式,适用于任意组件间通信。是根据VueComponent.prototype.__proto__=Vue.prototype的原理来进行全局引用二.全局事件总线......
  • Linux驱动开发十六.input系统——2.input_event
    我们上一章完成了input子系统的设备构成,并且在用户空间通过hexdump命令拿到了一堆不知道是什么的信息。今天我们就要借助input_event这个结构体来了解内核怎么通过那个结构......
  • C#中的委托(delegate)与事件(event)
    委托.NET团队之初想要实现一种用于任何后期绑定算法的引用类型,也就是想要一种可用于对方法引用的一种结构,同时又希望它能支持单播和多播,于是委托诞生了。......
  • EventOS - 超级轻量、事件驱动型嵌入式开发框架(转)
    转:EventOS-超级轻量、事件驱动型嵌入式开发框架 EventOS-超级轻量、事件驱动型嵌入式开发框架EventOS包含两个项目,分别是EventOSNano和EventOSBasic。Event......
  • # flask_socket_io中报错RuntimeError: You need to use the eventlet server. See th
    flask_socket_io中报错RuntimeError:Youneedtousetheeventletserver.SeetheDeploymentsectionofthedocumentationformoreinformation.的解决办法https:/......