Как внедрить интерфейс сервиса в конструктор контроллера в Nestjs?

#nestjs

#nestjs

Вопрос:

У меня есть приложение, которое получает сервис в качестве зависимости от контроллера, пока все хорошо, но я хотел бы найти способ вместо объявления конкретной реализации этого сервиса, чтобы иметь возможность «запрашивать» у контроллера интерфейс, который реализует этот сервис, для отделения от контроллера.конкретная реализация этого сервиса. Как это делается в nest js?

Ответ №1:

Для этого вам нужно создать токен для вашего интерфейса и использовать @Inject() декоратор с токеном для инъекций при внедрении вашего сервиса. Затем в вашем модуле вы можете объявить, какую реализацию предоставить для этого токена внедрения.

Ниже приведен простой интерфейс службы приветствия и наш токен внедрения, который будет использоваться при регистрации нашей службы в качестве поставщика.

приветствие-service.interface.ts

 // This will be our injection token.
export const GREETING_SERVICE = 'GREETING SERVICE';

export interface IGreetingService {
  greet(name: string): Promise<string>;
}
  

Базовая служба, которая будет реализовывать наш интерфейс приветствия…

professional-greeting.service.ts

 import { Injectable } from '@nestjs/common';
import { IGreetingService } from './greeting-service.interface';

@Injectable()
export class ProfessionalGreetingService implements IGreetingService {
  public async greet(name: string): Promise<string> {
    return `Hello ${name}, how are you today?`;
  }
}

  

И наш модуль приветствия, где мы регистрируем наш сервис с помощью токена…

приветствие.module.ts

 import { Module } from '@nestjs/common';
import { ProfessionalGreetingService } from './services/professional-greeting.service';
import { GREETING_SERVICE } from './services/greeting-service.interface';
import { GreetingController } from './controllers/greeting.controller';

@Module({
  providers: [
    {
      // You can switch useClass to different implementation
      useClass: ProfessionalGreetingService,
      provide: GREETING_SERVICE
    }
  ],
  controllers: [
    GreetingController
  ]
})
export class GreetingModule {}
  

Теперь, когда мы внедряем наш сервис, мы можем использовать @Inject() декоратор с нашим токеном внедрения. Какая бы реализация, которую вы продемонстрировали useClass в our GreetingModule , будет внедрена…

приветствие.controller.ts

 import { Controller, Get, Inject, Query } from '@nestjs/common';
import { GREETING_SERVICE, IGreetingService } from '../services/greeting-service.interface';

@Controller('greeting')
export class GreetingController {
  constructor(
    @Inject(GREETING_SERVICE)
    private readonly _greetingService: IGreetingService
  ) {}

  @Get()
  public async getGreeting(@Query('name') name: string): Promise<string> {
    return await this._greetingService.greet(name || 'John');
  }
}
  

https://jasonwhite.xyz/posts/2020/10/20/nestjs-dependency-injection-decoupling-services-with-interfaces/

https://github.com/jmw5598/nestjs-di-decoupling-with-interfaces
https://docs.nestjs.com/fundamentals/custom-providers