nest概念
module (模块)
按业务逻辑划分的基本单元,包含控制器和服务。控制器处理请求和响应数据,服务处理实际业务逻辑。
Middleware(中间件)
是路由处理前的数据处理层,只能在模块或者全局注册,可以做日志处理,用户认证等处理
Guard(守卫)
是决定请求是否可以到达对应的路由的处理器,可以做角色守卫
Pipe (管道)
是数据流处理,在中间件后路由处理前做数据处理,可以做数据验证,数据转换等数据处理
Interceptor(拦截器)
是进入控制器之前和之后处理相关逻辑,可以做日志,事务处理,异常处理,响应数据格式等
Exception filter (异常过滤)
是捕获错误信息,返回响应数据给客户端。可以做自定义行营异常格式
请求过程的执行顺序
- 中间件
- 守卫
- 拦截器(代码next.handle() 之前)
- 管道
- 路由处理
- 拦截器(代码next.handle()之后)
- 异常过滤器
DI 依赖注入
是一种重要的应用设计模式,在设计应用的时候时常会用到它,提升它们的开发效率和模块化程度。
- 利用@Injectable创建服务
我们创建的类提供了一个服务,@Injectable() 装饰器把它标记为可注入的服务,该注入器负责创建服务实例
cats.service.ts
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
findAll(): Cat[] {
return this.cats;
}
}
- 注册服务
将服务添加到@Module()装饰器的provider数组中
app.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
import { CatsService } from './cats/cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class AppModule {}
- 注入服务
通过构造函数注入依赖项
cats.controller.ts
import { Controller, Get } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';
@Controller('cats')
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
}
当注入器实例化 CatsController时,首先查找它所依赖项,当找到CatsService依赖项,将用CatsService令牌执行查找,并根据第二部返回 CatsService类。默认为单例,Nest将创建CatsService实例。将其缓存并返回,如果已经存在缓存,则返回现有的实例。
DI 提供者 provider
provider会使用DI令牌来配置注入器
标准提供者
标准提供者, 语法实际是一种简写:
provider: [Logger]
会被拓展为以下配置:
[{
provide: Logger,
useClass: Logger
}]
该配置是具有两个属性的对象字面量
provide: 令牌,它作为一个key,在定位依赖值和配置注入器使用。
useClass/ useExisting/useValue: 提供者对象,它告诉注入器要如何创建依赖值,每一种代表不用类型的依赖,下面会进行讨论
1 useValue 值提供者
值类型依赖,用于常量,函数,对象注入,有时候提供一个现成的对象会比注入器从类去创建更简单一些。如果注入一个已经创建过的对象,请使用useValue选项来配置该注入器。
2 useClass 类提供者
类依赖,动态确定令牌将解析为的类
3 useFactory 工厂提供者
工厂类型依赖,有时候需要动态创建依赖值,创建时需要的信息要等到运行期间才能拿到,当需要从第三方库创建依赖项实例时,工厂提供者也很有用,因为第三方库不是为DI而设计的。
4 useExisting 别名提供者
为现有的提供程序创建别名
provider有以下三个作用域
SINGLETON(defualt): 默认值,在程序启动时,将被实例化,单例将在整个应用程序中共享,实例可以被缓存,并且实例化仅发生一次
REQUEST: 每一个新的请求,都会创建一个新的实例,这个实例在请求结束后,将会被垃圾回收
TRANSIENT: 不跨消费者共享,注入该provider,都将有一个专用的实例