Skip to main content
Практика завдань

Що таке провайдери і як працює впровадження залежностей у NestJS?

Провайдери та впровадження залежностей у NestJS

Провайдери є основною концепцією в NestJS. Сервіси, репозиторії, фабрики, хелпери — все, що декороване @Injectable(), може бути провайдером. IoC контейнер NestJS автоматично управляє їхньою інстанціацією та впровадженням.


Сервіси (Найпоширеніший провайдер)

typescript
// users/users.service.ts import { Injectable, NotFoundException } from '@nestjs/common'; @Injectable() export class UsersService { private users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, ]; findAll() { return this.users; } findOne(id: number) { const user = this.users.find(u => u.id === id); if (!user) throw new NotFoundException(`Користувача #${id} не знайдено`); return user; } create(data: { name: string }) { const user = { id: Date.now(), ...data }; this.users.push(user); return user; } }

Впровадження сервісу в контролер

typescript
@Controller('users') export class UsersController { // NestJS автоматично впроваджує UsersService через конструктор constructor(private readonly usersService: UsersService) {} @Get() findAll() { return this.usersService.findAll(); } }

NestJS читає тип TypeScript UsersService і вирішує його з реєстру провайдерів модуля.


Сфери провайдерів

typescript
import { Injectable, Scope } from '@nestjs/common'; @Injectable({ scope: Scope.DEFAULT }) // Синглтон (за замовчуванням) — один екземпляр @Injectable({ scope: Scope.REQUEST }) // Новий екземпляр на запит @Injectable({ scope: Scope.TRANSIENT }) // Новий екземпляр на впровадження export class UsersService {}

Користувацькі провайдери

useValue — Впровадження константи

typescript
@Module({ providers: [ { provide: 'API_KEY', useValue: 'my-secret-key' }, ], }) export class AppModule {} // Впровадження з @Inject() @Injectable() export class ApiService { constructor(@Inject('API_KEY') private apiKey: string) {} }

useClass — Переопределення з іншим класом

typescript
@Module({ providers: [ { provide: LoggerService, useClass: MockLoggerService }, ], })

useFactory — Динамічний провайдер

typescript
@Module({ providers: [ { provide: 'DATABASE', useFactory: async (config: ConfigService) => { return await createDatabaseConnection(config.get('DB_URL')); }, inject: [ConfigService], }, ], })

useExisting — Псевдонім провайдера

typescript
{ provide: 'LoggerAlias', useExisting: LoggerService }

Впровадження між сервісами

typescript
@Injectable() export class PostsService { constructor( private readonly usersService: UsersService, // автоматично впроваджений private readonly emailService: EmailService, ) {} async createPost(userId: number, data: CreatePostDto) { const user = await this.usersService.findOne(userId); await this.emailService.sendNotification(user.email); // ... } }

Підсумок

Контейнер DI NestJS працює за рахунок:

  1. Сканування класів @Injectable(), зареєстрованих у провайдері модуля
  2. Читання типів параметрів конструктора (рефлексія TypeScript)
  3. Вирішення та впровадження правильних екземплярів

Це забезпечує слабке зв'язування, легке модульне тестування (мок-впровадження) та управління життєвим циклом (синглтони, запитово-скоповані тощо).

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань