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.mzph.cn/news/216234.shtml

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

相关文章

Windows编译动态库没有生成.lib文件问题

最近修改了一个项目,以前生成静态库,后改为生成动态库,在Linux上没有问题,但在Windows上只生成了.dll文件,没有生成.lib文件。 在Windows中,.lib文件除了可以用作静态链接库外,还有另一种用途&…

QT QIFW Windows下制作安装包(一)

一、概述 1、QIFW是一款基于QT框架开发的跨平台安装框架。QIFW是QT Installer FrameWork的缩写,支持Windows、Linux和macos等多种平台。QIFW可以帮助开发者创建自己的安装程序,将它们打包到通用的安装包中,并提供可视化的界面进行安装。 2…

Django分页器

1 Django的分页器(paginator)简介 在页面显示分页数据,需要用到Django分页器组件 from django.core.paginator import Paginator Paginator对象: paginator Paginator(user_list, 10) # per_page: 每页显示条目数量 # coun…

mysql:用SHOW CREATE TABLE tbl_name查看创建表的SQL语句

https://dev.mysql.com/doc/refman/8.2/en/show-create-table.html 可以用SHOW CREATE TABLE tbl_name查看创建表的SQL语句。 例如,SHOW CREATE TABLE test_table;表示查询创建test_table表的SQL语句:

刘元昌:期待更多年轻人的第一杯精酿是失眠企鹅

12月7日下午,2023(第十八届)大河财富中国论坛盛大开启。作为先行论坛,2023新消费峰会火热开场。此次峰会以“提质新消费 释放新活力”为主题,集论坛、演绎、展示、互动为一体,把峰会变身“秀场”&#xff0…

基于Java住院部病人信息管理系统

基于Java住院部病人信息管理系统 功能需求 1、病人信息管理:系统需要提供病人信息管理功能,包括病人的基本信息(如姓名、性别、年龄、联系方式等)和医疗信息(如病史、病情、诊断结果等)。 2、病房管理&a…

腾讯-轻量应用服务器centos7中宝塔安装MySQL8.0出现内存不足

目录 前言 出现的问题: 解决方法: 编译安装: 极速安装 其他 我的其他博客 前言 说实话,本人也就是个穷学生买不起啥大的服务器啥的,整了个2核 2内存的服务器 用宝塔按mysql5.5是没问题的,一切换8.0就提醒内存不足…

可信人工智能

定义 可信AI,就是确保AI的公平性、可解释性、健壮性和透明性,确保算法可被人信任。 存在的问题 算法不鲁棒导致的应用风险 自动驾驶汽车未能及时识别行人导致的交通事故黑箱模型导致算法难以解释,对用户不透明 难以推广至医疗、金融等需要…

UE5 - ArchvizExplorer与Map Border Collection结合 - 实现电子围栏效果

插件地址: https://www.unrealengine.com/marketplace/zh-CN/product/archviz-explorer https://www.unrealengine.com/marketplace/zh-CN/product/map-border-collection ArchvizExplorer扩展: https://download.csdn.net/download/qq_17523181/8843305…

freemarker+Aspose.word实现模板生成word并转成pdf

需求:动态生成pdf指定模板 实现途径:通过freemarker模板,导出word文档,同时可将word转为pdf。 技术选择思路 思路一:直接导出pdf 使用itext模板导出pdf 适用范围 业务生成的 pdf 是具有固定格式或者模板的文字及其…

数据采集网关:工业数据采集上云

数据采集网关,以其高效、便捷的特点,成为了现代工业物联网数据采集处理的重要工具。它是连接不同数据源和数据接收设备的桥梁,将各种形式和格式的数据快速、安全地汇聚到一起。通过数据采集网关,企业可以轻松实现数据的整合、转换…

函数创建与使用

函数使用的原因 函数是设计出来是为了完成某项功能的代码块。只要调用就能执行。实现代码复用。代码复用是不是复制,而是同样的代码不用写很多。只要用调用的代码来写,就能完成。将功能代码放到某个地方。函数的设计就是为了代码复用。 声明函数和调用…

《人性的弱点》读后感

《人性的弱点》这本书的每个章节都引人深思,让我对人性有了更深入的理解。以下是我对每个章节的读后感: 第一章:自我意识 这一章讲述了人性中最基本的一面,即自我意识。每个人都渴望被重视,希望得到他人的认可和赞赏…

【算法题】字符统计及重排(js)

解法&#xff1a; const str "xyxyXX"; const str1 "abababb"; function solution(str) {const strArr str.split("").sort((a, b) > a - b);const map new Map();for (let i 0; i < strArr.length; i) {if (map.has(strArr[i])) {m…

Chrome 将禁止修改 document.domain

参考链接1&#xff1a;https://developer.chrome.com/blog/immutable-document-domain?hlzh-cn 参考链接2&#xff1a;https://juejin.cn/post/7238980109453525050 为什么设置document.domain,跨域依旧报错&#xff1f;

推荐系统,推荐模型中负样本的选择和采集

推荐系统中&#xff0c;负样本的采集通常是一个挑战&#xff0c;因为用户往往只提供他们喜欢的项目的反馈&#xff0c;而不喜欢的项目的反馈通常是缺失的。以下是一些常见的负样本采集策略&#xff1a;   1. 随机采样&#xff1a;这是最常见的策略&#xff0c;就是从用户未互…

摇头机,舞台灯,白色家电,3D打印,医疗器械等安防芯片步进驱动选型GC系列,低成本,大电流

GLOBALCHIP新一代的安防产品用的芯片&#xff0c;GC3901 GC3909 GC3910 GC3911 GC8548 GC8549 GC6609 GC6610 GC2003 GC2803 GC2804步进驱动 达林顿选型型号&#xff0c;采用12V H 桥驱动器。其中最大持续电流(A)可达2.5A。其中GC6610&#xff0c;GC6609 是36V&#xff0c;低成…

Linux查询内存或CPU占用最多的几个进程

一、可以使用以下命令查使用内存最多的10个进程 方法1&#xff1a; ps -aux | sort -k4nr | head -10 如果是最高的三个&#xff0c;10改为3即可 命令解释&#xff1a; 1. ps&#xff1a;参数a指代all——所有的进程&#xff0c;u指代userid——执行该进程的用户id&#xff…

QT学习(2):信号槽机制

目录 信号槽机制定义连接一、标准connect链接1、QObject::connect2、QMetaObjectPrivate::connect3、信号槽容器Conntion、ConnectionList、SignalVector、ConnectionData 二、函数指针链接(qt5后)三、Lamba表达式 触发 信号槽机制 信号槽是观察者模式的一种实现&#xff0c;订…

14-Kafka-Day02

第 4 章 Kafka Broker 4.1 Kafka Broker 工作流程 4.1.1 Zookeeper 存储的 Kafka 信息 &#xff08;1&#xff09;启动 Zookeeper 客户端。 bin/zkCli.sh 因为你在配置kafka的时候指定了它的名字。 &#xff08;2&#xff09;通过 ls 命令可以查看 kafka 相关信息。 [zk: …