那家做网站好/市场调研报告1000字
Express.js 与 Nest.js对比
自从 Node.js
发布以来,Javascript
在后端领域的使用有所增加。由于 Node.js
的使用越来越多,每天都会有新的框架和工具发布。Express
和 Nest
是使用 Node.js
创建后端应用程序的最著名的框架之一,在本文中,我们将对它们进行比较。
Express
Express
是 Node.js
的简约框架。尽管它涵盖了创建服务器端应用程序的几个核心方面,但由于其简单性、灵活性和性能,它很流行,甚至 Nest
也是构建在 Express
之上的。但是,express
仍然存在一些问题,在我们深入研究这些问题之前,我们需要了解它们为我们提供了什么,让我们不使用任何框架而仅使用 Node.js
创建一个 Web
服务器。
const http = require("node:http");// Create a local server to receive data from
const server = http.createServer((req, res) => {res.writeHead(200, { "Content-Type": "application/json" });res.end(JSON.stringify({ message: "Hello World!" }));
});server.listen(8000);
在上面的代码中,我们使用 Node.js
中内置的 HTTP
模块创建一个 Web
服务器。如果我们向http://localhost:8000
发送 Web
请求,将从我们的 Node.js
服务器收到一条消息 (Hello World
)。
这很简单,但是如果我们想创建一个包含数百条不同路由的 REST API
该怎么办?然后我们必须编写一个路由匹配器并将每个路由发送到其特定的控制器。另外,我们必须实现 GET
、POST
、PUT
等 HTTP
方法来满足 REST
标准,对吗?Express
所做的正是这个,express
为我们处理请求/响应控制、路由、提供静态文件和中间件。这就是 Express
如此轻量和简单的美妙之处。现在让我们看看如何使用express
创建之前的应用程序。
const express = require("express");
const app = express();app.get("/", (req, res) => {res.send({ message: "Hello World" });
});app.listen(8000);
上面的代码也做了同样的事情。但是express
为我们提供了一个与请求的URL
匹配的路由机制,所以如果我们想使用express router
创建一个cat
路由,它会看起来像这样。
const express = require("express");
const app = express();
const router = express.Router();router.get("/", (req, res) => {res.send("Hello Cats");
});router.post("/create", (req, res) => {res.send("Create New Cat!");
});app.use("/cats", router);
app.listen(8000);
这很好,但是Express
有什么问题呢?Express
非常简约且直接,为用户提供了灵活性。灵活性对于有经验的用户或复杂的场景非常有利,但灵活性会导致错误和结构错误的增加。此外,现在的应用程序需要大量额外的逻辑,例如请求验证、授权、文档、测试、日志记录等。因此,Express
只为我们提供了一些功能,人们需要使用其他库或框架来解决这些需求。这就是 Nest.js
存在的原因。
Nest
Nest
是一个用于构建高效、可扩展的 Node.js
服务器端应用程序的框架。Nest
构建在常见 Node.js
框架(Express
、Fastify
)之上。它使用渐进式 JavaScript
,使用 TypeScript
构建并完全支持 TypeScript
(但仍然允许开发人员使用纯 JavaScript
进行编码),并结合了 OOP
(面向对象编程)、FP
(函数式编程)和 FRP
(函数式反应式编程)的元素。
Nest
在这些常见 Node.js
框架(Express/Fastify
)之上提供抽象,并将其 API
直接公开给开发人员。这使开发人员可以自由地使用可用于底层平台的无数第三方模块。Nest
的目的是创建高度可测试、可扩展、松散耦合且易于维护的应用程序。
为了证明这一点,让我们使用 Nest
重构之前的应用:
import { Controller, Get, Post } from '@nestjs/common';
@Controller('cat')
export class CatController {@Get()getCats() {return 'Hello World';}@Post('create')create() {return 'Create New Cat!';}
}
Nest
的路由方法与控制器配合使用,控制器可以组织路由并使路由更清晰、更易于管理。Nest
有一个默认的错误处理程序和其他内置实用程序,可帮助我们快速入门。当然,可以用express
手动实现它们,但不需要重新发明轮子。所有这些便利设置使 Nest
成为初学者的更好选择,因为这些核心实用程序对于初学者来说可能很难理解。
对比
现在我们了解了这些框架的基础知识,让我们深入了解、对比一下Express
和Next
。
1. 架构
在 Express
中,没有架构标准。这在许多大型项目或微服务应用程序中成为一个问题,因为它们需要强大而灵活的架构来保持应用程序的可维护性。
另一方面,Nest
最强大的一面是架构,因为 Nest
有许多实用程序来提供灵活、干净且强大的架构。Nest-Modules
就是一个很好的例子。Nest-Module
用于组织应用程序结构并帮助开发人员管理模块的依赖关系。
Nest
还非常适合应用 N 层架构,旨在将应用程序划分为逻辑层。层是一种分离职责和管理依赖关系以实现关注点分离 (SoC
) 原则的方法。为了实现这一目标,Nest
建议调用控制器内的服务层,并在这些服务层内执行所有业务逻辑。对于服务层,调用另一个层称为存储库层,该层负责数据访问。因此,我们将我们的关注点分为三层。分离这些层可以为软件提供可重用性和可维护性。它还使我们的应用程序易于测试,
我们创建的cat
路由,它可能看起来像这样:
CatController -> CatService -> CatRepository
因此,每当我们需要在任何控制器中调用 CatService
的方法时,我们只需创建 CatService
的实例并调用该方法,或者我们可以通过将 CatService
实例作为 CatController
构造函数的参数传递来使用现有的 CatService
实例,即Nest
还有一个概念叫做依赖注入。
2. 依赖注入
依赖注入是一种设计模式,其中一个对象接收它所依赖的其他对象。依赖注入是控制反转的一种形式,旨在分离构造对象和使用对象的关注点,从而导致松散耦合的程序。
在 Nest
中,可以通过在要注入的模块顶部添加 Injectable
装饰器来使用依赖注入。例如
import { Injectable } from '@nestjs/common';
@Injectable()
export class CatService {findAll() {return 'Hello World';}create() {return 'Create New Cat!';}
}
import { Controller, Get, Post } from '@nestjs/common';
import { CatService } from './cat.service';@Controller('cat')
export class CatController {constructor(private readonly catService: CatService) {}@Get()getCats() {return this.catService.findAll();}@Post('create')create() {return this.catService.create();}
}
正如我们所看到的,我们将 catService
实例作为参数传递给 CatController
的构造函数。这种方法使应用程序更易于维护且易于测试,尤其是对于大型应用程序。这是使用 Nest
的最大优势之一。
3. 中间件
默认情况下,Nest
中间件相当于 Express
中间件。在 Express
中间件中,我们只需创建另一个在控制器之前/之后运行的路由处理程序。Nest
有一个MiddlewareConsumer
类,它是一个辅助类。它提供了几种内置方法来管理中间件。所有这些都可以简单地以流畅的方式链接起来。MiddlewareConsumer
有一个forRoutes
属性,我们可以在其中简单地输入字符串或控制器的路径来注册中间件。Nest
还有一个exclude
属性,可以帮助我们排除路径或控制器。
Nest
还提供类似中间件的实用程序,例如管道、过滤器和拦截器。它们可以被认为是中间件,但它们更专注于不同的目的。例如,管道主要用于验证和数据转换。另一方面,中间件是在路由处理程序之前运行的处理程序,并且可以访问请求对象。过滤器与中间件相反。它们在路由处理程序之后运行并操作响应对象以进行错误处理等。最后,拦截器可以在调用路由处理程序之前和之后访问请求和响应对象。
Nest
还提供了一个名为 ExecutionContext
的实用程序,它提供有关当前执行过程的其他详细信息,例如接下来要执行的内容,而 Express
中间件则缺少此信息。
4. 自定义异常
Nest
为大多数场景提供了默认的异常类,例如 NotFoundException
、UnAuthorizedException
等。这可以节省我们一些时间。此外,还可以像在express
中一样创建自己的异常类。
5. 验证
请求验证在很多方面都是有益的。它可以防止错误发生,并向用户显示一条有意义的消息,表明他们发送了错误的输入。此外,它还可以防止用户发送不需要的输入,从而使应用程序更加安全。
在express
中,我曾经在处理程序之前添加一个中间件,这个中间件采用一个验证器作为参数,该验证器是使用Joi
工具创建的。但这非常耗时,并且会导致我们的路由/处理程序声明看起来更长、更复杂,并且有时候会忘记在处理程序之前添加验证器。不可能创建可在整个应用程序的所有上下文中使用的通用中间件。这是因为中间件不知道执行上下文,包括将被调用的处理程序及其任何参数。
6. 授权
授权是后端应用程序中的常见需求。某些服务可能需要基于角色的授权以防止不允许的操作。授权通常由传统 Express
应用程序中的中间件处理,通常看起来像这样。
router.get('/create', authorize(Role.Admin), create);
Nest
的授权方式类似,但 Nest
通过其Guards
概念提供了一些便利。守卫确定给定的请求是否将由路由处理程序处理。防护可以是控制器范围、方法范围或全局范围,这在实现中提供了易用性,也有助于保持代码干燥和声明性。此外,执行上下文可用于构建通用防护,这使得防护比传统中间件更强大。
@Post()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto);
}
7. 数据库
在express
中我们通常使用 ORM
(对象关系映射器)或ODM
(对象文档映射器)如Sequelize
或Mongoose
来处理数据库操作。Nest
没有什么不同,但 Nest
具有内置的 ORM-ODM
工具,这些工具提供模型/存储库注入、可测试性和动态配置,以便访问我们选择的数据库,我认为,Nest
的架构使使用数据库变得更容易
8.API文档
迄今为止,在 Nest.js
中记录 API
是最简单的。Nest
提供了一个 swagger
模块,可以自动为 API
端点创建文档。此外,还可以使用如下装饰器定义请求/响应模式。
@ApiBody({ type: CreateCatDto })@ApiCreatedResponse({ type: CreateCatResponseDto })create(@Body() createSampleDto: CreateCatDto) : CreateCatResponseDto{// ...}
9. 性能
Nest
允许使用 Fastify
适配器,它比 Express
适配器快两倍,如果不使用 Fastify
适配器,Nest
将无法击败 Express
。我们知道 Nest
提供了这两个适配器的抽象以在它们之间进行切换,但这在每种情况下都是不可能的,因为在某些情况下这两个适配器的行为本质上不同。例如,fastify
适配器不支持嵌套路由,因此应该使用 Express
适配器来实现这一点。
10. 测试
Nest
最强大的架构优势也在这里获胜。正如我们之前讨论的那样,Nest
使用模块并将它们与依赖项注入结合起来,这允许将任何依赖项注入到任何模块,因此我们可以注入测试服务而无需实例化它,并且它可以节省大量时间和精力,特别是对于较大的模块和服务。
相关文章:

Express.js 与 Nest.js对比
Express.js 与 Nest.js对比 自从 Node.js 发布以来,Javascript 在后端领域的使用有所增加。由于 Node.js 的使用越来越多,每天都会有新的框架和工具发布。Express 和 Nest 是使用 Node.js 创建后端应用程序的最著名的框架之一,在本文中&…...

总结 CNN 模型:将焦点转移到基于注意力的架构
一、说明 在计算机视觉时代,卷积神经网络(CNN)几十年来一直是主导范式。直到 2021 年 Vision Transformers (ViTs) 出现,这个领域才开始发生变化。现在,是时候采用受 Transformer 架构启发的基于注意力的模型了&#x…...

2023.11.16 hivesql高阶函数之开窗函数
目录 1.开窗函数的定义 2.数据准备 3.开窗函数之排序 需求:用三种排序方法查询学生的语文成绩排名,并降序显示 4.开窗函数分组 需求:按照科目来分类,使用三种排序方式来排序学生的成绩 5.聚合函数与分组配合使用 6.聚合函数同时和分组以及排序关键字配合使用 --需求1&…...

QTableWidget常用信号的功能
2023年11月18日,周六上午 itemPressed(QTableWidgetItem *item):当某个项目被按下时发出信号。itemClicked(QTableWidgetItem *item):当某个项目被单击时发出信号。itemDoubleClicked(QTableWidgetItem *item):当某个项目被双击时…...

Vue理解01
项目建立流程 项目文件夹终端vue ui可视化新建项目(需要一些时间)vscode打开项目npm run serve运行 架构理解: 首先打开的页面默认是index.htmlindex.html默认引用main.jsmain.js引用需要的页面,默认App.vue。Vue示例挂载可以在…...

4、FFmpeg命令行操作8
生成测试文件 找三个不同的视频每个视频截取10秒内容 ffmpeg -i 沙海02.mp4 -ss 00:05:00 -t 10 -codec copy 1.mp4 ffmpeg -i 复仇者联盟3.mp4 -ss 00:05:00 -t 10 -codec copy 2.mp4 ffmpeg -i 红海行动.mp4 -ss 00:05:00 -t 10 -codec copy 3.mp4 如果音视…...

【MySQL】索引与事务
作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《MySQL》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造&a…...

切换为root用户后,conda:未找到命令
问题:切换为root用户后,conda:未找到命令 结论详细用户切换配置路径 结论 问题:切换为root用户后,conda:未找到命令 (anaconda) 解决:在~/.bashrc配置里增加conda的路径 详细 用户切换 1 切…...

Qt退出界面
void Dialog::on_pushButton_clicked() {if(ui->lineEdit->text() "admin" && ui->lineEdit_2->text() "123"){accept();//退出} }...

【数据标注】Label Studio用于机器学习标注
原文作者:我辈李想 版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、使用 Label Studio标注数据1.版本控制 二、Label Studio绑定机器学习后端三、重写机器学习后端四、通过api执行Label Studio动作 前言…...

py字符串转字符串数组
在Python中,你可以使用列表(list)来存储多个字符串。如果你有一个字符串,并且想要将其转换为字符串数组,你可以使用列表推导式(list comprehension)。这是一个简单的例子: # 原始字…...
强化学习各种符号含义解释
:状态 : 动作 : 奖励 : 奖励函数 : 非终结状态 : 全部状态,包括终结状态 : 动作集合 ℛ : 奖励集合 : 转移矩阵 : 离散时间步 : 回合内最终时间步 : 时间t的状态 : 时间t动作 : 时间t的奖励,通常为随机量,且由和决定 : 回报 : n步…...

Axure基础详解二十:中继器随机抽奖效果
效果演示 组件 一、中继器 建立一个“中继器”内部插入一个“正方形”,给“正方形”添加一个【样式效果】>>【选中状态】填充背景为红色,字体白色。在中继器表格中插入两列数据函数:【xuhao】(序号列,按12345……填写&…...

企业信息化与电子商务>供应链信息流
1.供应链信息流概念 供应链信息流是指整个供应链上信息的流动。它是一种虚拟形态,包括了供应链上的供需信息和管理信息,它伴随着物流的运作而不断产生。因此有效的供应链管理作为信息流的管理主要作用在于及时在供应链中传递需求和供给信息,…...

【Proteus仿真】【STM32单片机】防火防盗GSM智能家居设计
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器,使用声光报警模块、LCD1602显示模块、DS18B20温度、烟雾传感器模块、按键模块、PCF8591 ADC模块、红外检测模块等。 主要功能: 系统运行…...

快速入门ESP32——开发环境配置PlatformIO IDE
相关文章 快速入门ESP32——开发环境配置Arduino IDE 快速入门ESP32——开发环境配置PlatformIO IDE 一、下载安装二、验证 一、下载安装 下载安装 vscode 安装PlatformIO插件 创建工程 二、验证 写一个简单的函数来验证一下功能 void setup() {// put your setup cod…...

Oxygen XML Editor 26版新功能
▲ 搜索“大龙谈智能内容”关注GongZongHao▲ 2023年10月26日,罗马尼亚SyncRO Soft公司发布Oxygen XML Editor、Oxygen Web Author和Oxygen Publish Engine 26版本。 1. Oxygen XML Editor 26新功能简介 AI助手 帮助写作者通过执行重复任务、审查语法、生成结构…...

Pikachu漏洞练习平台之SSRF(服务器端请求伪造)
注意区分CSRF和SSRF: CSRF:跨站请求伪造攻击,由客户端发起; SSRF:是服务器端请求伪造,由服务器发起。 SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标…...

WPF异步编程
在WPF应用程序中进行异步编程是非常重要的,因为这有助于保持用户界面的响应性,特别是当执行长时间运行的操作时,例如访问网络资源、进行大量的数据处理或调用耗时的I/O操作。 WPF的异步编程通常围绕以下几个关键概念: Dispatcher…...

同态加密定义,四大发展阶段总结,FHE系统正式定义-全同态加密
目录 同态加密定义 为什么采用电路模型? 四大发展阶段 总结 FHE系统正式定义...

网上的搜索
Internet中蕴含的信息资源非常丰富,但如何在这浩瀚如海的信息空间内快速找到自己所需要的资源呢?我们需要借助于搜索引擎。在网络上,提供搜索功能的网站非常多,如百度、谷歌、搜狗等,另外有一些门户网站也提供了搜索功能…...

【算法-哈希表2】快乐数 和 两数之和
今天,带来哈希表相关算法的讲解。文中不足错漏之处望请斧正! 理论基础点这里 1. 快乐数 分析题意 出题者已经把题意明确告诉我们了: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&am…...

MR外包团队:MR、XR混合现实技术应用于游戏、培训,心理咨询、教育成为一种创新的各行业MR、XR形式!
随着VR、AR、XR、MR混合现实等技术逐渐应用于游戏开发、心理咨询、培训、教育各个领域,为教育、培训、心理咨询等行业带来了全新的可能性。MR、XR游戏开发、心理咨询是利用虚拟现实技术模拟真实场景,让学生身临其境地参与学习和体验,从而提高…...

【P1008 [NOIP1998 普及组] 三连击】
[NOIP1998 普及组] 三连击 题目背景 本题为提交答案题,您可以写程序或手算在本机上算出答案后,直接提交答案文本,也可提交答案生成程序。 题目描述 将 1 , 2 , … , 9 1, 2, \ldots , 9 1,2,…,9 共 9 9 9 个数分成 3 3 3 组ÿ…...

机器学习算法——集成学习
目录 1. Bagging 1. Bagging Bagging(bootstrap aggregating:自举汇聚法)也叫装袋法,其思想是通过将许多相互独立的学习器的结果进行结合,从而提高整体学习器的泛化能力,是一种并行集成学习方法。 工作流…...

java springboot在当前测试类中添加临时属性 不影响application和其他范围
目前 我们的属性基本都写在 application.yml 里面了 但是 如果 我们只是想做一下临时变量的测试 有没有办法实现呢? 显然是有的 这里 我们还是先在application.yml中去写一个 test属性 下面加个prop 然后 我们尝试在测试类中 获取一下这个属性 直接用 Value 读取…...

原型网络Prototypical Network的python代码逐行解释,新手小白也可学会!!由于工作量大,准备整8个系列完事,-----系列5
文章目录 前言一、原始程序---计算原型,开始训练,计算损失二、每一行代码的详细解释2.1 粗略分析2.2 每一行代码详细分析 前言 承接系列4,此部分属于原型类中的计算原型,开始训练,计算损失函数。 一、原始程序—计算原…...

milvus数据库的数据管理-插入数据
一、插入数据 1.准备数据 数据必须与数据库中定义的字段元数据一致,与集合的模式匹配 import random data [[i for i in range(2000)],[str(i) for i in range(2000)],[i for i in range(10000, 12000)],[[random.random() for _ in range(2)] for _ in range(2…...

系列一、请谈谈你对JVM的理解?Java8的虚拟机有什么更新?
一、请谈谈你对JVM的理解?Java8的虚拟机有什么更新? JVM是Java虚拟机的意思。它是建立在操作系统之上的,由类加载器子系统、本地方法栈、Java栈、程序计数器、方法区、堆、本地方法库、本地方法接口、执行引擎组成。 (1࿰…...

恕我直言,大模型对齐可能无法解决安全问题,我们都被表象误导了
是否听说过“伪对齐”这一概念? 在大型语言模型(LLM)的评估中,研究者发现了一个引人注目的现象:当面对多项选择题和开放式问题时,模型的表现存在显著差异。这一差异根源在于模型对复杂概念的理解不够全面&…...