上手nestjs
如何安装nestjs
因为后续会选择nestjs创建不同的应用,所以推荐安装nestjs的官方生成工具
1 | |
因为nestjs完全支持使用typescript构建,所以传递 –strict 可以使项目有更加严格的功能集
创建提示如下:
1 | |
默认此命令是安装好所有的依赖,所以你可以直接进入到project-name目录并直接输入npm run start运行项目
当终端出现如下命令,即表示项目启动成功
1 | |
表示nest正在启动nest应用,然后初始化了AppModule,初始化了一个Appcontroller,路由为 /,然后 / 下有一个 GET 方法,最终nest应用成功启动,这意味着,我们可以在127.0.0.1:3000/ 直接发送一个GET请求,返回了 “Hello World!”
1 | |
如何编写nestjs代码
首先我们通过npm run start:dev可以运行服务并监视文件中的更改
这样当我们编写nestjs代码的时候,保存文件后,nestjs将会重新编译,提升开发效率
nestjs推荐安装 eslint 和 prettier 两个包来统一开发的 lint 和 format
如何debug代码
方式一:vscode断点调试
这里以vscode为例,通常用来开发ts相关的项目
我们来到运行和调试一栏,主动添加配置,选择 nodejs:通过npm启动
然后在configurations中就会出现以下配置
1 | |
此时我们可以修改配置:
1 | |
此时我们即可通过点击 debug nestjs 左侧的绿色执行按钮启动项目并支持断点调试
方式二:官方的devtools
需要付费
主要是查看模块间的依赖关系以及是否有循环依赖
了解nestjs的基础概念
Controllers
控制器:主要负责处理传入的请求并将响应发送回客户端
你可以理解为路由的入口,通过不同的模块申明不同的入口,例如user模块,就会有以下restful资源
- 【获取所有用户信息】GET /user
- 【获取单个用户信息】GET /user/:id
- 【新增某个用户信息】POST /user/:id
- 【更新某个用户信息】PATCH /user/:id
- 【删除某个用户信息】DELETE /user/:id
在此资源之上,你可以通过装饰器来申明通过什么路径来调用、获取请求参数、重定向、错误处理等等
providers
提供程序:nestjs的核心概念,很多nestjs的基础类都是被看作是提供程序,例如 services, repositories, factories, helpers。关键的思想是依赖注入(DI)
- provider不是手动new出来的,而是由nest的 IOC 容器来负责provider的实例化以及生命周期的管理
- 每个provider只需要负责完成它自己的功能,控制器只负责路由,逻辑复用和扩展交给provider
| 配置方式 | 示例 | 使用场景 | 设计理念 | 总结 |
|---|---|---|---|---|
| useClass | [ { provide: Token, useClass: Logger } ] |
用某个类作为实现,常用于替换具体实现 开发环境用consoleLogger, 生产用fileLogger |
面向接口编程。只要 token 一致,背后实现可随时切换。 | 面向抽象,随时换实现 |
| useValue | [ { provide: Token, useValue: { db: 'mysql', port: 3306 } } ] |
注入常量、配置项、工具函数等 | 值即是服务,直接把一个对象或函数注册到 IoC 容器,避免硬编码。 | 配置即依赖,简单直接 |
| useFactory | [ { provide: Token, useFactory: (config: ConfigService) => new DB(config.dbUrl), inject: [ConfigService] } ] |
构造逻辑复杂,依赖其他 provider 的场景。 | 工厂模式 + DI。容器只管执行工厂函数,返回什么就注入什么。 | 动态构造,灵活注入 |
| useExisting | [ { provide: Token, useExisting: ConsoleLogger } ] |
给已有 provider 起别名。 例:AppLoggerToken 与Token 指向同一实例。 |
“指针”绑定。多个 token 引用同一 provider,避免重复实例化。 | 别名绑定,复用实例 |
Modules
modules:提供 Nest 用于有效组织和管理应用程序结构的元数据
providers:Nest 注入器将实例化的提供程序,这些程序至少可以在本模块中共享
controllers:本模块中定义的、需要实例化的控制器集合
imports:本模块所需的提供程序的模块列表(从其他模块export之后再在本模块import)
exports:这些提供程序由本模块提供,并应在导入本模块的其他模块中可用。您可以使用提供程序本身,也可以只使用其标记(提供值)
Middleware
中间件是在路由处理程序之前调用的函数,中间件函数可以访问请求和响应对象,以及应用程序请求-响应周期中的 next() 中间件函数
几乎等同于express的中间件
Exception filters
Exception filters:负责处理应用程序中所有未处理的异常
通常用来处理HTTP标准异常、自定义异常、业务异常以及未捕捉到的异常
Pipes
pipes的作用
- 转换:将输入数据转换为所需的形式(例如,从字符串转换为整数)
- 验证:评估输入数据,如果有效,只需将其原封不动地传递;否则,抛出异常
Guards
guards:守卫是一个用 @Injectable() 装饰器注释的类,它实现了 CanActivate 接口。
作用:只有一个责任。它们确定给定请求是否由路由处理程序处理,具体取决于运行时存在的某些条件(如权限、角色、ACL 等)。这通常称为授权。
Interceptors
Interceptors:拦截器是一个用 @Injectable() 装饰器注释的类,实现了 NestInterceptor 接口。
功能:
- 在方法执行之前/之后绑定额外的逻辑
- 转换从函数返回的结果
- 转换从函数抛出的异常
- 扩展基本函数行为
- 根据特定条件完全覆盖函数(例如,用于缓存目的)
了解nestjs核心模块的执行顺序
【nest应用启动时初始化】
sequenceDiagram
participant AppModule
participant NestFactory
participant IoCContainer as IoC 容器
participant Provider
participant Controller
NestFactory->>AppModule: 读取根模块
AppModule->>NestFactory: 返回 imports/controllers/providers
NestFactory->>IoCContainer: 注册 Providers
IoCContainer->>Provider: 实例化依赖 (构建依赖树)
NestFactory->>Controller: 注册 Controllers & 路由
Note over NestFactory,Controller: 应用初始化完成
【请求生命周期】
sequenceDiagram
participant Client
participant Middleware
participant Guard
participant Interceptor as Interceptor(before)
participant Pipe
participant Controller
participant Service
participant InterceptorAfter as Interceptor(after)
participant ExceptionFilter
participant Response
Client->>Middleware: 进入应用
Middleware->>Guard: 继续
Guard->>Interceptor: canActivate 成功
Interceptor->>Pipe: before handler
Pipe->>Controller: 参数验证 & 转换
Controller->>Service: 调用业务逻辑
Service-->>Controller: 返回数据
Controller->>InterceptorAfter: 结果返回
InterceptorAfter->>Response: 加工结果后响应
Note over Guard,Response: 如果任意阶段抛错 → ExceptionFilter 捕获