Nest 学习笔记:Nest.js 和后端的几个概念
前言
今天尝试写了个 Nest.js 的 Demo,但是发现好像一堆东西看不懂,拿 AI 问了下才知道具体是什么,把 AI 说的总结了一下放着自己看。(所以这篇文章带了 AI 辅助生成的标签)
概念
Nest.js 是一个基于 Node.js 构建的进阶框架,它使用 TypeScript 编写,具备模块化、依赖注入等特性,帮助开发者快速构建高性能和可扩展的服务端应用。Nest.js 是围绕着 面向对象编程(OOP) 和 依赖注入(DI) 的设计理念开发的。
模块化结构
概念
在 Nest.js 中,应用是由多个模块(Module)组成的,模块包含控制器(Controller)、服务(Service)、提供者(Provider)等。每个模块可以将业务逻辑分离成独立的单元,使代码易于维护和扩展。
案例
以 AppModule 为例。
import { Module } from '@nestjs/common';
import { TodoController } from './todo/todo.controller';
import { TodoService } from './todo/todo.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Todo } from './todo/todo.entity';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'sqlite',
database: 'todo.db',
entities: [Todo],
synchronize: true,
}),
TypeOrmModule.forFeature([Todo]),
],
controllers: [TodoController],
providers: [TodoService],
})
export class AppModule {}
@Module()
:标记为一个模块,它包含了控制器和服务。通过imports
引入 TypeORM 配置来连接数据库。controllers
:定义了哪些控制器处理 HTTP 请求。providers
:注册服务(例如TodoService
),这些服务可以在整个模块中被使用。
控制器(Controller)
概念
控制器用于处理 HTTP 请求(如 GET、POST、PUT、DELETE 等),它负责接受客户端的请求并将其转发给服务层处理。Nest.js 中的控制器是通过 @Controller()
装饰器定义的。
案例
以TodoController 为例。
import { Controller, Get, Post, Delete, Param, Body } from '@nestjs/common';
import { TodoService } from './todo.service';
import { Todo } from './todo.entity';
@Controller('todos')
export class TodoController {
constructor(private readonly todoService: TodoService) {}
@Get()
getAllTodos(): Promise<Todo[]> {
return this.todoService.findAll();
}
@Post()
createTodo(@Body('title') title: string): Promise<Todo> {
return this.todoService.create(title);
}
@Delete(':id')
deleteTodo(@Param('id') id: number): Promise<void> {
return this.todoService.remove(id);
}
}
解释
@Controller('todos')
:将控制器定义为/todos
路径下的所有请求处理器。constructor(private readonly todoService: TodoService)
:通过依赖注入将TodoService
注入到控制器中。@Get()
:处理 GET 请求,调用todoService
获取所有任务。@Post()
:处理 POST 请求,创建新的任务。@Delete(':id')
:处理 DELETE 请求,删除指定 ID 的任务。
服务(Service)
概念
服务是用来处理业务逻辑的类。服务通常通过依赖注入的方式被控制器调用,并负责与数据库或其他外部资源交互。
案例:
以 TodoService 为例。
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Todo } from './todo.entity';
@Injectable()
export class TodoService {
constructor(
@InjectRepository(Todo)
private readonly todoRepository: Repository<Todo>,
) {}
async create(title: string): Promise<Todo> {
const newTodo = this.todoRepository.create({ title, completed: false });
return this.todoRepository.save(newTodo);
}
async findAll(): Promise<Todo[]> {
return this.todoRepository.find();
}
async remove(id: number): Promise<void> {
await this.todoRepository.delete(id);
}
}
解释
@Injectable()
:标记TodoService
类为可被注入的服务,Nest.js 会自动创建并管理它的实例。@InjectRepository(Todo)
:注入Todo
实体的仓库,用于与数据库表交互。create()
:创建新任务,并保存到数据库。findAll()
:从数据库中获取所有任务。remove()
:根据任务 ID 删除任务。
依赖注入(Dependency Injection,DI)
概念
依赖注入是 Nest.js 的核心概念之一。通过 DI,类的依赖对象(如服务)可以在类的构造函数中被自动注入,避免类自己管理依赖的创建过程。DI 使得代码更易测试和维护。
案例:控制器中的依赖注入
constructor(private readonly todoService: TodoService) {}
解释
todoService
是通过依赖注入注入到控制器中的。在AppModule
中注册的TodoService
会自动被注入。
实体(Entity)与 TypeORM
概念
实体(Entity)表示数据库中的表结构,TypeORM 允许开发者使用面向对象的方式与数据库交互。每个实体类都对应数据库中的一张表。
案例
以 Todo 实体为例。
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Todo {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column({ default: false })
completed: boolean;
}
解释
@Entity()
:将Todo
类标记为数据库表。@PrimaryGeneratedColumn()
:定义了一个自增的主键id
列。@Column()
:定义了表的普通列,如title
(任务标题)和completed
(任务是否完成)。
异步
因为数据库操作通常是异步的,Nest.js 通过 Promise
来处理这些异步操作。Promise<T>
表示这个操作最终会返回一个 T
类型的值(例如 Todo
)。
async create(title: string): Promise<Todo> {
const newTodo = this.todoRepository.create({ title, completed: false });
return this.todoRepository.save(newTodo);
}
Promise<Todo>
:表示这个异步操作最终会返回一个Todo
实体。async
和await
:允许我们以同步的方式编写异步代码。
总结
- Nest.js 是模块化和依赖注入驱动的框架:每个应用由模块、控制器和服务组成,模块管理控制器和服务,服务处理业务逻辑并通过依赖注入与控制器协作。
- TypeORM 提供数据库交互能力:通过实体类与数据库表进行映射,
Repository
提供对数据库的增删查改操作。 - 依赖注入减少了类与类之间的耦合:Nest.js 自动管理类的依赖,提升了代码的灵活性和可维护性。