tips

121 阅读4分钟

Tips1

NestJS 使用大量的装饰器来增强其框架功能和提升代码的可读性。这些装饰器广泛应用于定义控制器、服务、模块、中间件等。由于装饰器数量众多,下面我列出一些最常用的,并解释它们的作用。接着,我会解释 @Module 装饰器中的各个属性。

常见 NestJS 装饰器

控制器装饰器

  • @Controller(prefix?): 定义一个基本控制器。prefix 是可选的,用于定义所有路由的前缀。
  • @Get(path?), @Post(path?), @Put(path?), @Delete(path?), 等: 定义对应 HTTP 方法的路由处理程序。path 是可选的。

请求处理装饰器

  • @Req(), @Res(), @Next(): 注入原生的请求、响应对象和 next 函数。
  • @Body(param?), @Query(param?), @Param(param?): 获取请求体、查询参数或路由参数。

服务和模块装饰器

  • @Injectable(): 标记一个类可以作为依赖注入的服务。
  • @Module(): 定义 NestJS 模块。

参数装饰器

  • @Inject(token): 显式注入依赖。

其他装饰器

  • @Guard(), @UseGuards(guards): 用于方法或控制器的认证守卫。
  • @Middleware(): 定义中间件。
  • @Pipe(), @UsePipes(pipes): 使用管道。
  • @ExceptionFilter(), @UseFilters(filters): 使用异常过滤器。

@Module 装饰器属性

  • providers: 由 Nest 注入器实例化的提供者数组。通常用于服务、存储库、工厂等。
  • controllers: 用于定义当前模块中的一组控制器。
  • imports: 列出导入当前模块所需的其他模块。
  • exports: 定义提供者的子集,可在其他模块中使用。仅当提供者在 providers 数组中定义并且需要跨模块共享时使用。
  • providers: 一个当前模块所需提供者的数组,这些提供者可以是服务、存储库、工厂、助手等。

以上内容涵盖了 NestJS 中最常见的装饰器及 @Module 装饰器的属性。请注意,NestJS 是一个不断发展的框架,可能会随着新版本引入更多的装饰器和功能。🔧🤖🔨💡

Tips2

用在Entity class 的方法之上

user=repo.create(UserEntity)--->repo.save(user) √ Hooks are executed

user=repo.create(UserEntity)---> but ---> repo.save({email:"xxx.com",password:"xxx"}) × Hooks not executed

NestJS 结合 TypeORM 使用时,提供了一系列的装饰器来处理实体的生命周期事件。这些装饰器通常用于实体类中,允许你定义在特定操作(如插入、更新或删除)发生时执行的逻辑。下面是一些最常用的生命周期事件装饰器及其解释:

@BeforeInsert()

  • 用途: 用在实体类的方法上。这个方法会在实体被插入到数据库之前自动调用。
  • 场景: 常用于在保存实体之前自动填充或修改某些字段,如设置创建时间戳、哈希密码等。

@AfterInsert()

  • 用途: 用在实体类的方法上。这个方法会在实体成功插入到数据库之后自动调用。
  • 场景: 适用于需要在新记录创建后执行操作的场景,如日志记录、触发某些业务逻辑等。

@BeforeUpdate()

  • 用途: 用在实体类的方法上。这个方法会在实体更新之前自动调用。
  • 场景: 常用于在更新实体之前处理某些逻辑,例如更新修改时间戳。

@AfterUpdate()

  • 用途: 用在实体类的方法上。这个方法会在实体更新到数据库之后自动调用。
  • 场景: 用于更新操作之后的逻辑,如记录历史更改、通知等。

@BeforeRemove()

  • 用途: 用在实体类的方法上。这个方法会在删除实体之前自动调用。
  • 场景: 在删除记录前执行必要的清理工作或检查,例如确保记录可以安全删除。

@AfterRemove()

  • 用途: 用在实体类的方法上。这个方法会在实体从数据库中删除之后自动调用。
  • 场景: 删除操作后的处理,如从缓存中清除、记录删除操作等。

示例

typescriptCopy code
import { Entity, PrimaryGeneratedColumn, Column, BeforeInsert, AfterInsert } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  password: string;

  @BeforeInsert()
  async hashPassword() {
    this.password = await someHashFunction(this.password);
  }

  @AfterInsert()
  logInsert() {
    console.log(`Inserted User with id ${this.id}`);
  }
}

在这个示例中,hashPassword 方法将在每次将 User 实体插入数据库之前自动调用,而 logInsert 方法则会在插入操作后调用。

这些生命周期钩子提供了一种优雅的方式来处理和封装与实体相关的业务逻辑。🔧🤖🔨💡