首页文章关于

Nestjs-学习笔记

nodejsserver architecture

Nestjs作为一个在nodejs框架(expressfastify、...)之上的抽象层提供了可扩展、可测试、多样性(rest apimicroservicesweb socketsgraphql)、渐进式的架构解决方案,可以满足各种后端的需求场景

基础

CLI

nest cli提供了系列模板代码创建以及启动、打包命令

shell
pnpm add -g @nest/cli
// 创建nest项目-new
nest new project-name
// 启动项目-start
nest start | start:dev
// 构建项目-build
nest build
// 查看项目详情-info
nest info
// 导入外部嵌套库
nest add xxx
// 生成模板代码-generate
nest generate controller | module | middleware | ...
// 查看所有|指定命令
nest -h
nest <command> -h

Controller

controller作为mvc模型中逻辑的最小单元nest为此提供了很多便利修饰符以供使用

ts
/* import { ... } from "@nestjs/common" */
// 一级路由构成: http://localhost:3000/things
@Controller('things')
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
findAll(): string {
return 'This action return all things'
}
// 使用分页查询: http://localhost:3000/things?limit=10&offset=0
@Get()
findPartial(@Query() paginationQuery) {
const { limit, offset } = paginationQuery;
return `This action returns partion things. Limit: ${limit} Offset: ${offset}`;
}
// 路由参数: http://localhost:3000/hello/123
@Get(':id')
findOne(@Param('id') id:string) {
return `This action returns #${id} one`
}
// 返回传递过来的body
@Post()
@HttpCode(HttpStatus.OK)
create(@Body() body) {
return body;
}
// 使用框架风格返回
@Get()
findAllUsePlatform(@Res() res) {
res.status(200).send('This action returns all things');
}
@Put(':id')
update(@Param('id') id: string, @Body() body) {
return ''
}
}

Providers

provider(services、repositories、helpers、etc)作为controller的依赖注入到其构造函数中用以拆分业务逻辑并在内部使用

controller.ts
ts
import { ThingsService } from "./things.service.ts"
@Controller('things') mk
export class ThingsController {
construct(private readonly thingsService: ThingsService) {}
findAll() {
return this.thingsService.findAll();
}
// ...
}
things.entity.ts
ts
export class Things {
id: number;
name: string;
brand: string;
flavors: string[];
}
things.service.ts
ts
import { Things } from "../entities/things.entity.ts"
export class ThingsService {
private things: Things[] = [
{
id: 1,
name: 'Auu',
brand: 'someone',
flavors: ['a', 'b'],
},
];
findAll() {
return this.things;
}
// ...
}

Modules

@Module是用来聚合一个业务模块所需要的关联组件(controller、provider)又可以通过imports来复用其他模块的入口层用以拆分业务模块,每个应用至少有一个根模块

app.module.ts
ts
@Module({
imports: [CoffeesModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
things.module.ts
ts
@Module({
controllers: [ThingsController],
providers: [ThingsService],
})
export class ThingsModule {}

DTO

DTO(data transfer object)用来规定api入参及返回数据的形式及类型接口,通过useGlobalPipes搭配class-validator以解决类型安全及参数校验一旦参数不满足则返回400状态提示

createSomeThing.dto.ts
ts
import { IsString } from 'class-validator';
export class CreateSomeThingDto {
@IsString()
readonly name: string;
@IsString()
readonly brand: string;
@IsString({ each: true })
readonly flavors: string[];
}

使用@nestjs/mapped-types对于现有DTO字段规则进行复用

updateSomeThing.dto.ts
ts
import { PartialType } from '@nestjs/mapped-types';
import { CreateSomeThingDto } from './create-something.dto';
export class UpdateSomeThingDto extends PartialType(CreateSomeThingDto) {}
things.controller.ts
ts
@Post()
create(@Body() createCoffeeDto: CreateCoffeeDto) {
return this.coffeesService.create(createCoffeeDto);
}
main.ts
ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({
whitelist: true, // 忽略dto指定外的字段
transform: true, // 转换入参为指定类型用以匹配对应的DTO
forbidNonWhitelisted: true, // 禁止dto指定外的字段,会有400提示
}));
await app.listen(3000);
}

Dependency Injection

范式约定

  • 对于api风格的推荐使用非特定框架写法
ts
findSomeTHing() {
return 'xxx';
}
  • 对于api错误信息推荐使用Expection Layer返回特定场景的错误提示
ts
if (!something) {
throw new HttpException(`SomeThing not found`, HttpStatus.NOT_FOUND);
}
Copyright © 2023, Daily learning records and sharing. Build by