Node.js 事件循环简单介绍

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.hqwc.cn/news/267941.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python入门第6篇(FastApi、uvicorn)

前言 FastApi用来开发webapi,可以定义路由、定义get、post方法等 但是要让浏览器可以访问webapi,还需要用到uvicorn,即web服务器,类似Tomcat、iis这种的 pip安装相关包 FastApi uvicorn 注意:可能一次安装不成功…

系列十、SpringBoot + MyBatis + Redis实现分布式缓存(基于注解方式)

一、概述 上篇文章 系列九、SpringBoot MyBatis Redis实现分布式缓存 介绍了基于xml方式实现分布式缓存的效果,当前大家使用的技术栈基本是springboot各种框架的组合,而springboot显著的一个特点就是去xml配置,那么在无xml配置的情形下&…

mysql:建议使用INT UNSIGNED类型存储IPv4地址

建议使用INT UNSIGNED类型存储IPv4地址,而不要使用INT类型,也不建议使用VARCHAR(15)类型存储。 在mysql中,内嵌函数INET_ATON(expr)可以将IP地址字符串转换为整数,内嵌函数INET_NTOA(expr)可以将整数转换为ip地址字符串。 例如&a…

使用Kali Linux端口扫描

端口扫描 【实训目的】 掌握端口扫描的基本概念和端口扫描的原理,掌握各种类型端口扫描的方法及其区别。 【场景描述】 在虚拟机环境下配置4个虚拟系统“Win XP1” “Win XP2” “Kali Linux”和“Metasploitable2”,使得4个系统之间能够相互通信。实…

.net6 打包成exe文件启动后,只能localhost访问,无法使用ip访问

背景: 公司其他部门采用了.net6开发了一个小服务,需要我这边部署到winserver上,由于之前没有了解过.net6,就直接进行部署了,发现点击exe直接启动了,也没报错,在服务器上也可以通过localhost进行访问&#…

六级翻译之印章

好像大房子挺难得 三段式 1Since ancient from now,seals have been a symbol of power and certerfiction of identity.seals not only practical but also is a form of art.Seal is an ancient art combining with manafutuer of crafting and desgin of…

arkts编译报错-arkts-limited-stdlib错误【Bug已完美解决-鸿蒙开发】

文章目录 项目场景:问题描述原因分析:解决方案:适配指导案例此Bug解决方案总结项目场景: arkts编译报错-arkts-limited-stdlib错误。 我用Deveco studio4.0 beta2开发应用,报arkts-limited-stdlib错误 报错内容为: ERROR: ArKTS:ERROR File: D:/prRevivw/3792lapplica…

胡桃工具箱 原神多功能工具箱

胡桃工具箱 原神胡桃工具箱是一款非常实用的游戏工具辅助软件,可以为用户们提供优质的原神游戏工具,体验更精彩的游戏辅助,提供帧率解锁游戏功能,包括数据查询、游戏详解以及各种实用的功能。 安装使用 1.获取胡桃工具箱 请点击…

EasyExcel处理表头的缓存设置

在学习EasyExcel 时会发现针对使用类模型配置表头相关属性时,EasyExcel 会使用到缓存技术以提升表头的解析速度如下代码: 这些参数再何时设置的哪? 在easyExcel 基础参数设置中会有这个参数filedCacheLocation 。默认采用的使用线程级别的…

华为或荣耀手机禁止强制升级鸿蒙系统的终极方法

需要有数据传输的usb线.打开usb调试模式. 进这个链接下载华为ADB一键卸载VS重装软件 按里面的视频说明,输入88 然后回车即可 https://download.csdn.net/download/viqecel/12161462

【神行百里】pandas查询加速之行索引篇

最近进行大数据处理的时候,发现我以前常用的pandas查询方法太慢了,太慢了,真是太慢了,查阅资料,遂发现了一种新的加速方法,能助力我飞上天,和太阳肩并肩,所以记录下来。 1. 场景说明…

HyperGCN代码复现

环境:python3.6.7,torch0.4,外加pyyaml。 问题1:TypeError: cant convert np.ndarray of type numpy.intc. The only supported types are: double, float, float16, int64, int32, and uint8. 解决办法: 复现结果: …