Node.js 事件循环简单介绍

news2024/12/22 15:33:15

1.简介

Node.js 事件循环是 Node.js 运行时环境中的一个核心机制,用于管理异步操作和回调函数的执行顺序。它基于事件驱动模型,通过事件循环来处理和派发事件,以及执行相应的回调函数。

  • Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
  • Node.js 几乎每一个 API 都是支持回调函数的。
  • Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。
  • Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.

2.Node.js事件循环流程分析

Node.js 事件循环的主要步骤包括:

  • 执行同步代码:首先,Node.js 会执行当前代码中的同步任务,以及它们所调用的同步函数。
  • 执行异步代码:若有异步操作(例如 I/O 操作或网络请求),Node.js 会将其放入事件队列(Event Queue)中,然后继续执行后续的同步任务。
  • 处理事件队列:当同步任务执行完毕或达到一个阈值时,Node.js 将开始处理事件队列。它会依序取出事件队列中的事件,执行相应的回调函数,并处理可能的新事件。
  • 重复上述步骤:Node.js 会重复执行前述的步骤,直到事件队列为空。

对于每个事件的处理过程,Node.js 会执行以下操作:

  • 执行回调函数:Node.js 会将事件从事件队列中取出,然后执行与该事件相关联的回调函数。
  • 执行可能的同步操作:回调函数的执行过程中,可能会引发新的同步操作,Node.js 会立即执行这些同步操作。
  • 返回控制权:回调函数的执行完毕后,Node.js 将返回控制权给事件循环,继续处理下一个事

总结:
Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。

当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。

这个模型非常高效可扩展性非常强,因为 webserver 一直接受请求而不等待任何读写操作。(这也称之为非阻塞式IO或者事件驱动IO)

在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。

在这里插入图片描述
整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。

3.时间循环举例说明

Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件,如下实例:

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
 
// 创建事件处理程序
var connectHandler = function connected() {
   console.log('连接成功。');
  
   // 触发 data_received 事件 
   eventEmitter.emit('data_received');
}
 
// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);
 
// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){
   console.log('数据接收成功。');
});
 
// 触发 connection 事件 
eventEmitter.emit('connection');
console.log("程序执行完毕。");

执行结果:

$ node test_event.js
连接成功。
数据接收成功。
程序执行完毕。

4.Node.js工作解析

当你运行一个 Node 应用程序时,它会经历以下步骤:

  • 初始化:Node.js 在启动应用程序之前进行初始化操作,加载所需的模块和依赖项。
  • 执行顶层代码:Node.js 开始执行应用程序的顶层代码,包括变量声明、函数定义等同步操作。
    下面是一个简单的例子:
const http = require('http');

function onRequest(request, response) {
  response.writeHead(200, { 'Content-Type': 'text/plain' });
  response.write('Hello, World!');
  response.end();
}

const server = http.createServer(onRequest);
server.listen(3000);
console.log('Server is running on port 3000');

在这个例子中,我们通过 http 模块创建了一个 HTTP 服务器,并将其绑定到 3000 端口。当服务器收到请求时,会调用 onRequest 函数处理请求并返回响应。

  • 异步操作和回调函数:Node.js 在执行顶层代码后,处理应用程序中的异步操作。这包括处理网络请求、文件读写、数据库查询等。举个例子,假设我们的应用程序要读取一个文件并将其中的内容打印到控制台:
const fs = require('fs');

fs.readFile('data.txt', 'utf8', function (error, data) {
  if (error) {
    console.error('Error:', error);
    return;
  }
  console.log('File content:', data);
});

在这个例子中,我们使用 fs 模块异步地读取名为 data.txt 的文件。读取操作完成后,调用回调函数来处理读取的文件内容。

  • 事件循环:Node.js 的事件循环在后台运行,不断地检查事件队列,并执行相应的回调函数。
    如果我们将上述的 HTTP 服务器和文件读取的例子结合起来:
const http = require('http');
const fs = require('fs');

function onRequest(request, response) {
  fs.readFile('data.txt', 'utf8', function (error, data) {
    if (error) {
      response.writeHead(500, { 'Content-Type': 'text/plain' });
      response.write('Internal Server Error');
      response.end();
      return;
    }
    response.writeHead(200, { 'Content-Type': 'text/plain' });
    response.write(data);
    response.end();
  });
}

const server = http.createServer(onRequest);
server.listen(3000);
console.log('Server is running on port 3000');

现在,当收到 HTTP 请求时,服务器会异步地读取文件,并在读取完成后发送文件内容作为响应。

  • 关闭应用程序:当应用程序终止或手动关闭时,Node.js 会执行一些清理操作并释放资源。
    上述例子中的应用程序可以通过按下 Ctrl+C 组合键来关闭。
    Node.js 的运行方式使它适用于处理高并发和实时应用程序,因为它能够以非阻塞的方式处理异步操作,提供高性能和可伸缩性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1305839.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java版Spring Cloud+Spring Boot+Mybatis之隐私计算 FATE - 多分类神经网络算法测试

一、说明 本文分享基于 Fate 使用 横向联邦 神经网络算法 对 多分类 的数据进行 模型训练,并使用该模型对数据进行 多分类预测。 二分类算法:是指待预测的 label 标签的取值只有两种;直白来讲就是每个实例的可能类别只有两种 (0 或者 1)&…

SpringBoot系列之基于Jedis实现分布式锁

Redis系列之基于Jedis实现分布式锁 1、为什么需要分布式锁 在单机环境,我们使用最多的是juc包里的单机锁,但是随着微服务分布式项目的普及,juc里的锁是不能控制分布锁环境的线程安全的,因为单机锁只能控制同个进程里的线程安全&…

独立完成软件的功能的测试(3)

独立完成软件的功能的测试(3) (12.13) 执行测试用例 缺陷相关知识 缺陷的定义:软件再使用过程中出现的错误,Bug 评判标准 少功能,需求规格说明书中明确要求的功能功能错误多功能隐性功能错误…

【1.计算机组成与体系结构】流水线技术

目录 1.流水线的定义2.相关参数计算2.1 流水线计算公式2.2 流水线的吞吐率2.3 流水线加速比计算 3.超标量流水线 1.流水线的定义 流水线是指在程序执行时多条指令重叠进行操作的一种准并行处理实现技术。各种部件同时处理是针对不同指令而言的,它们可同时为多条指令…

【FPGA/verilog -入门学习9】verilog基于查找表的8位格雷码转换

本文参考:FPGA杂记5——格雷码转换设计-CSDN博客 1,什么是查表法,做什么用,有什么好处 查找表(Look-Up-Table) 查找表,简单说,就是一个预先存储好结果的数据表 通过访问这张预先存储…

解决:WARNING: Ignoring invalid distribution -ip (d:\python37\lib\site-packages)

解决:WARNING: Ignoring invalid distribution -ip (d:\python37\lib\site-packages) 文章目录 解决:WARNING: Ignoring invalid distribution -ip (d:\python37\lib\site-packages)背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结…

CentOS 7 离线安装MySQL审计插件

命令行 cd /data/toolssz mariadb-10.2.38-linux-x86_64.tar.gztar -zxvf mariadb-10.2.38-linux-x86_64.tar.gzinstall lib/plugin/server_audit.so /usr/lib64/mysql/plugin/mysql -uroot -prootinstall plugin server_audit SONAME server_audit.so;show variables like &q…

【图论-匈牙利算法】Hungary Algorithm完整代码(一) 之 matlab实现

学习参考链接 博客 分配问题与匈牙利算法 带你入门多目标跟踪(三)匈牙利算法&KM算法 视频 运筹学 | 例题详解指派问题 前言 图论-匈牙利算法原理参见上述参考连接中的博客与BiliBili博主的学习视屏,讲的很好很透彻。强烈建议看完&#…

Idea maven打包时 报错 illegalArgumentException: Malformed \uxxxx encoding 解决方法

1 改变打包命令重新打包 在maven打包命令上加入 -e -X 2 找到报错类和方法 可以看到是 java.util.Properties#loadConvert类方法中有个throw new IllegalArgumentException( "Malformed \\uxxxx encoding."),在此打断点 3 以Debug方式重新运行maven…

原创改进|多策略融合的改进蜣螂优化算法

作者在前段时间的一篇文章中介绍过了蜣螂优化算法(dung beetle optimizer,DBO)的原理及实现,该算法是由东华大学沈波教授团队在2022年提出[1],其灵感来自蜣螂的滚球、跳舞、觅食、偷窃和繁殖行为这5种习性,其不同的子种群执行了不…

IntelliJ IDEA v2023.3发布——持续演进AI辅助工具、支持Java 21

IntelliJ IDEA,是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具,尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超常的。 I…

Python 自动化之处理docx文件(一)

批量筛选docx文档中关键词 文章目录 批量筛选docx文档中关键词前言一、做成什么样子二、基本架构三、前期输入模块1.引入库2.路径输入3.关键词输入 三、数据处理模块1.基本架构2.如果是docx文档2.1.读取当前文档内容2.2.遍历匹配关键字2.3.触发匹配并记录日志 3.如果目录下还有…

如何利用宝塔面板和docker快速部署网站

当你有了一台服务器,就会折腾往这台服务器上部署各种好玩的网站。市面上有许多开源的网站项目,通过docker技术可以快速部署并使用,本文将以部署filebrowser举例介绍网站部署的基本流程。 1. 安装宝塔面板 宝塔面板是一款开源的网站运维工具…

云服务器部署可视化Docker私有仓库(Ubuntu)

这里测试的机器为ubuntu22.04 一、环境安装 docker安装就不赘述了 先升级,再从官方仓库安装docker compose apt update apt upgrade apt install docker-compose二、部署私有仓库UI Docker提供了一个叫registry的镜像,给大家搭建私有仓库&#xff0c…

如何在nacos中的配置在不同的环境服务下可实现配置共享

其实在微服务启动时,会去nacos读取多个配置文件,例如: [spring.application.name].yaml,例如:nacos-order-service.yaml[spring.application.name]-[spring.profiles.active].yaml,例如:nacos-o…

《地理信息系统原理》笔记/期末复习资料(10. 空间数据挖掘与空间决策支持系统)

目录 10. 空间数据挖掘与空间决策支持系统 10.1. 空间数据挖掘 10.1.1. 空间数据挖掘的概念 10.1.2. 空间数据挖掘的方法与过程 10.1.3. 空间数据挖掘的应用 10.2. 空间决策支持系统 10.2.1. 空间决策支持系统的概念 10.2.2. 空间决策支持系统的结构 10.2.3. 空间决策…

Flink 有状态流式处理

传统批次处理方法 【1】持续收取数据(kafka等),以window时间作为划分,划分一个一个的批次档案(按照时间或者大小等); 【2】周期性执行批次运算(Spark/Stom等)&#xff1b…

Vue3-04-reactive() 响应式失效的三种情况

1.替换对象后导致失效 简单理解 : 变量指向的对象换了,对原来的对象,当然没有了响应式的效果了。// 声明 变量let obj1 reactive({name:"第一个对象"})// 改变 变量的指向obj1 reactive({name:"第二个对象的属性"})co…

三天精通Selenium Web 自动化 - Selenium(Java)环境搭建 (new)

0 背景 开发工具idea代码管理mavenjdk1.8webdriver chrome 1 chromedriver & chrome chromedriver和chrome要对应上: chomedriver下载地址:淘宝镜像 这里用的是 chromedriver88-0-4324-96.zipchrome下载地址:如何降级和安装旧版本的C…

【计算机网络基础3】ARP/RARP协议、路由选择协议和TCP/IP协议

1、ARP/RARP协议 地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确…