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

什么是事件循环(Event Loop)?浏览器和 Node.js 中的事件循环有什么区别?

首先,JavaScript是一门单线程的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环。

JavaScript中,所有的任务都可以分为

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行

  • 异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等

什么是事件循环(Event Loop)?

事件循环是 JavaScript 实现异步编程的核心机制之一,用于协调同步代码、异步任务(宏任务、微任务)的执行顺序,避免代码阻塞。

同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就事件循环

详细说就是:先进行同步任务、执行过程中遇到宏任务或微任务放到各自队列。同步任务执行完了以后先查看微任务队列中有没有任务,执行队列所有任务以后再取一个宏任务进行执行,这样一个循环往复的过程就是事件循环。管理异步API的回调函数什么时候回到主线程中执行。

事件循环的组成部分
  1. 调用栈(Call Stack):JavaScript引擎用来跟踪函数调用和返回值的栈结构。

  2. 任务队列(Task Queues):存储待执行的异步任务。不同的异步任务会被放入不同的队列中,如宏任务队列(Macro Task Queue)和微任务队列(Micro Task Queue)。

  3. 事件循环(Event Loop):不断检查调用栈和任务队列,确保任务按顺序执行。

浏览器和 Node.js 中的事件循环有什么区别?

浏览器中的事件循环:

  1. 执行同步代码,遇到异步任务(宏任务、微任务)分别放入对应队列;
  2. 同步代码执行完毕后,清空所有微任务队列(按顺序执行);
  3. 微任务执行完毕后,执行一个宏任务,然后再次清空微任务队列,循环往复。

  • 宏任务:setTimeout、setInterval、DOM 事件、AJAX 请求;
  • 微任务:Promise.then/catch/finally、async/await、MutationObserver。

微任务通常比宏任务有更高的优先级,会在当前宏任务执行完毕后立即执行,但在下一个宏任务开始之前。

Node.js 中的事件循环:

在Node中的事件循环分为六个阶段:

  1. timer定时器阶段:执行如setTimeout和setInterval等的回调函数
  2. close callbacks关闭回调阶段:执行socket.close()事件回调
  3. check检查阶段:执行setImmediate的回调函数
  4. Poll轮询阶段:这是一个至关重要的阶段,系统主要做两件事,一是回到timer阶段执行回调,二是执行I/O回调。会主动检测是否有新的I/O事件,若存在新的I/O事件,则执行其回调函数,适当的条件下,node将阻塞在这里。
  5. Idle闲置阶段:仅供系统内部使用
  6. I/O回调 阶段:执行上一轮循环中未执行的I/O回调函数

  • 微任务:Promise.then/catch/finally、process.nextTick、queueMicrotask
  • 宏任务:setlnterval、setimeout、setlmmediate、I/O事件、close事件
注意:浏览器的事件循环和node事件循环有什么区别?

1、 微任务队列执行时机不同。在浏览器事件循环中, 每执行完一个宏任务,便要检查并执行微任务队列、而node事件循环中microtask 微任务会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行 microtask 微任务队列的任务。

2、 特定API:Node.js有process.nextTicksetImmediate,而浏览器没有

浏览器事件循环流程:执行一个宏任务 -> 清空所有微任务 -> 执行下一个宏任务 -> 清空所有微任务 -> ...

Node.js 事件循环流程:执行完Timers阶段的所有宏任务 -> 清空所有微任务 -> 进入下一个阶段...

简单来说:

  1. 浏览器是一个宏任务+一个微任务队列
  2. node是一个宏任务队列+一个微任务队列

例子:

setTimeout(()=>{console.log('timer1')Promise.resolve().then(function() {console.log('promise1')})
}, 0)
setTimeout(()=>{console.log('timer2')Promise.resolve().then(function() {console.log('promise2')})
}, 0)浏览器端运行结果:timer1=>promise1=>timer2=>promise2
Node 端运行结果:timer1=>timer2=>promise1=>promise2
console.log('script开始');
setTimeout(() => {console.log('宏任务1');Promise.resolve().then(function () {console.log('微任务2')})
},0);setTimeout(() => {console.log('宏任务2');Promise.resolve().then(function() {console.log('微任务3')})
})Promise.resolve().then(function () {console.log('微任务1');
})console.log('script结束');//浏览器端运行结果
script开始
script结束
微任务1
宏任务1
微任务2
宏任务2
微任务3//node端运行结果
script开始
script结束
微任务1
宏任务1
宏任务2
微任务2
微任务3

http://www.dtcms.com/a/349389.html

相关文章:

  • springboot整合druid(多数据源配置)
  • Python_occ 学习记录 | 阵列
  • 李沐-第十章-训练Seq2SeqAttentionDecoder报错
  • 十九、云原生分布式存储 CubeFS
  • 剧本杀APP系统开发:打造多元化娱乐生态的先锋力量
  • Go编写的轻量文件监控器. 可以监控终端上指定文件夹内的变化, 阻止删除,修改,新增操作. 可以用于AWD比赛或者终端应急响应
  • TensorFlow深度学习实战(34)——TensorFlow Probability
  • GO学习记录八——多文件封装功能+redis使用
  • Node.js(2)—— Buffer
  • 安卓Android低功耗蓝牙BLE连接异常报错133
  • Docker Compose 部署 Elasticsearch 8.12.2 集成 IK 中文分词器完整指南
  • Go初级三
  • 上海AI实验室突破扩散模型!GetMesh融合点云与三平面,重塑3D内容创作
  • 少儿舞蹈小程序需求规格说明书
  • AutoCAD Electrical缺少驱动程序“AceRedist“解决方法
  • 【STM32】G030单片机的独立看门狗
  • ELKB日志分析平台 部署
  • 完美世界招数据仓库工程师咯
  • ArcGIS JSAPI 高级教程 - 创建渐变色材质的自定义几何体
  • three.js+WebGL踩坑经验合集(8.3):合理设置camera.near和camera.far缓解实际场景中的z-fighting叠面问题
  • 大数据平台ETL任务导入分库分表数据
  • Jenkins+docker 微服务实现自动化部署安装和部署过程
  • TDengine IDMP 应用场景:电动汽车
  • AI测试工具midsence和browse_use的使用场景和差异
  • react+taro打包到不同小程序
  • Flutter旧版本升级-> Android 配置、iOS配置
  • 机器视觉的3C玻璃盖板丝印应用
  • KeepAlived+Haproxy实现负载均衡(SLB)
  • window显示驱动开发—混合系统 DDI 和 dList DLL 支持
  • Shell 循环编程:for 与 select 轻松入门