乐闻世界logo
搜索文章和话题

NestJS 提供者和服务的作用是什么?

2月17日 22:30

提供者(Provider)的概念

提供者是 NestJS 中的一个核心概念,它是一个用 @Injectable() 装饰器装饰的类,可以被注入到其他类中。提供者可以处理业务逻辑、数据访问、与其他服务的集成等。

提供者的类型

  1. 服务(Services):封装业务逻辑
  2. 仓库(Repositories):处理数据访问
  3. 工厂(Factories):创建和配置对象
  4. 提供者(Providers):任何可以被注入的类

服务(Service)

服务是最常见的提供者类型,用于封装业务逻辑和可重用的功能。

基本服务结构

typescript
import { Injectable } from '@nestjs/common'; @Injectable() export class UsersService { private readonly users: any[] = []; create(user: any) { this.users.push(user); return user; } findAll() { return this.users; } findOne(id: number) { return this.users.find(user => user.id === id); } update(id: number, updateUserDto: any) { const user = this.findOne(id); if (user) { Object.assign(user, updateUserDto); return user; } return null; } remove(id: number) { const index = this.users.findIndex(user => user.id === id); if (index > -1) { this.users.splice(index, 1); return true; } return false; } }

在控制器中使用服务

typescript
import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common'; import { UsersService } from './users.service'; @Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) {} @Post() create(@Body() createUserDto: any) { return this.usersService.create(createUserDto); } @Get() findAll() { return this.usersService.findAll(); } }

在模块中注册提供者

方式一:直接提供类

typescript
import { Module } from '@nestjs/common'; import { UsersController } from './users.controller'; import { UsersService } from './users.service'; @Module({ controllers: [UsersController], providers: [UsersService], }) export class UsersModule {}

方式二:使用 provide 和 useClass

typescript
@Module({ providers: [ { provide: UsersService, useClass: UsersService, }, ], }) export class UsersModule {}

方式三:使用 provide 和 useValue

typescript
@Module({ providers: [ { provide: 'API_KEY', useValue: 'your-api-key-here', }, ], }) export class AppModule {}

方式四:使用 provide 和 useFactory

typescript
@Module({ providers: [ { provide: UsersService, useFactory: (userRepository: UserRepository) => { return new UsersService(userRepository); }, inject: [UserRepository], }, ], }) export class UsersModule {}

方式五:使用 provide 和 useExisting

typescript
@Module({ providers: [ UsersService, { provide: 'USERS_SERVICE', useExisting: UsersService, }, ], }) export class UsersModule {}

依赖注入令牌

类作为令牌

typescript
constructor(private readonly usersService: UsersService) {}

字符串作为令牌

typescript
constructor(@Inject('API_KEY') private readonly apiKey: string) {}

Symbol 作为令牌

typescript
export const API_KEY = Symbol('API_KEY'); constructor(@Inject(API_KEY) private readonly apiKey: string) {}

作用域配置

默认作用域(单例)

typescript
@Injectable() export class UsersService {}

请求作用域

typescript
import { Scope } from '@nestjs/common'; @Injectable({ scope: Scope.REQUEST }) export class UsersService {}

瞬时作用域

typescript
@Injectable({ scope: Scope.TRANSIENT }) export class UsersService {}

自定义提供者

异步提供者

typescript
@Module({ providers: [ { provide: 'ASYNC_CONNECTION', useFactory: async () => { const connection = await createConnection(); return connection; }, }, ], }) export class AppModule {}

动态模块

typescript
import { DynamicModule, Module } from '@nestjs/common'; @Module({}) export class DatabaseModule { static register(options: DatabaseOptions): DynamicModule { return { module: DatabaseModule, providers: [ { provide: 'DATABASE_OPTIONS', useValue: options, }, DatabaseService, ], exports: [DatabaseService], }; } }

最佳实践

  1. 单一职责原则:每个服务只负责一个功能领域
  2. 依赖注入:使用构造函数注入依赖
  3. 接口隔离:定义清晰的接口契约
  4. 避免循环依赖:设计时避免服务间的循环依赖
  5. 使用 DTO:使用数据传输对象来传递数据
  6. 错误处理:在服务层处理业务逻辑错误
  7. 可测试性:编写可测试的服务代码
  8. 文档化:为服务添加清晰的文档注释

服务层设计模式

1. 仓储模式(Repository Pattern)

typescript
@Injectable() export class UserRepository { constructor(private readonly dataSource: DataSource) {} async findById(id: number) { return this.dataSource.getRepository(User).findOne({ where: { id } }); } async findAll() { return this.dataSource.getRepository(User).find(); } }

2. 服务模式(Service Pattern)

typescript
@Injectable() export class UsersService { constructor( private readonly userRepository: UserRepository, private readonly emailService: EmailService, ) {} async createUser(createUserDto: CreateUserDto) { const user = await this.userRepository.create(createUserDto); await this.emailService.sendWelcomeEmail(user.email); return user; } }

3. 工厂模式(Factory Pattern)

typescript
@Injectable() export class UserFactory { createUser(data: any): User { return new User(data); } }

总结

NestJS 提供者和服务系统提供了:

  • 灵活的依赖注入机制
  • 多种提供者注册方式
  • 清晰的代码组织结构
  • 高度的可测试性
  • 良好的可维护性

掌握提供者和服务是构建 NestJS 应用程序的核心,它们使开发者能够编写松耦合、可重用和可测试的代码。通过合理使用提供者和服务,可以构建出结构清晰、易于维护的企业级应用。

标签:NestJS