当前位置: 首页 > 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.xdnf.cn/news/1364545.html

相关文章:

  • 维度建模 —— 雪花模型 和 星型模型的优缺点
  • 冯·诺依曼架构:现代计算机的基石与瓶颈
  • Linux驱动开发笔记(七)——并发与竞争(下)——自旋锁信号量互斥体
  • k8s笔记03-常用操作命令
  • vite 项目创建、插件配置
  • JBL音响代理——河北正娱科技的声学精品工程
  • 智慧城市SaaS平台/交通设施运行监测系统之桥梁运行监测、城市道路塌陷风险运行监测系统架构内容
  • 网络编程--TCP/UDP Socket套接字
  • 验证码流程
  • 【AI解读源码系列】ant design mobile——Space间距
  • 京东API分类接口实战指南:获取各类商品信息
  • 【大模型本地运行与部署框架】Ollama的API交互
  • Spring拦截器中@Resource注入为null的问题
  • PAT乙级_1120 买地攻略_Python_AC解法_含疑难点
  • 6.3Element UI 的表单
  • 【python断言插件responses_validator使用】
  • 分布式系统与单机系统的优劣势对比
  • Reachability Query
  • Linux系统编程——进程 | 线程
  • 直播美颜SDK技术解析:人脸美型功能的算法原理与实现方案
  • TCP与HTTP协议以及爬虫
  • 如何在Debian服务器上设置Node.js日志轮转
  • cs61a中的递归小例子
  • 创建高效MCP客户端:多服务器环境解决方案指南
  • 决策树原理与 Sklearn 实战
  • Hadoop MapReduce Task 设计源码分析
  • 【C++高并发内存池篇】ThreadCache 极速引擎:C++ 高并发内存池的纳秒级无锁革命!
  • 【目标跟踪】《FastTracker: Real-Time and Accurate Visual Tracking》论文阅读笔记
  • 论文阅读:Code as Policies: Language Model Programs for Embodied Control
  • uniapp中加载.urdf后缀的3D模型(three.js+urdf-loader)