Skip to main content

Що таке провайдер (provider)?

Провайдер (Provider) в NestJS - це будь-який клас, який можна впровадити (інжектувати) в інші класи через систему Dependency Injection (DI). Простіше кажучи, провайдер - це те, що надає якийсь функціонал чи дані, і може використовуватися іншими компонентами (контролерами, сервісами, гвардами, пайпами тощо).

Основна ідея

Провайдер - це об'єкт, який створюється й керується NestJS. Nest сам вирішує:

  • коли створити екземпляр провайдера;
  • як впровадити його в потрібні класи;
  • скільки копій має існувати (за замовчуванням - singleton, тобто один спільний екземпляр).

Простий приклад провайдера

javascript
import { Injectable } from '@nestjs/common'; @Injectable() export class UsersService { private users = [{ id: 1, name: 'John' }]; findAll() { return this.users; } }

Цей UsersService - провайдер, тому що він позначений декоратором @Injectable(). Його можна впровадити в контролер чи інший сервіс:

javascript
import { Controller, Get } from '@nestjs/common'; import { UsersService } from './users.service'; @Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) {} @Get() getUsers() { return this.usersService.findAll(); } }

Як NestJS створює й впроваджує провайдери

  1. Кожен провайдер реєструється в @Module() (у секції providers).
  2. NestJS поміщає всі провайдери в DI-контейнер (IoC контейнер).
  3. Коли інший клас вказує залежність у конструкторі, NestJS автоматично знаходить і впроваджує потрібний екземпляр.

Типи провайдерів

Тип провайдераПрикладОпис
Клас-провайдер@Injectable() class UsersService {}Найпоширеніший тип
Значення (value) провайдер{ provide: 'CONFIG', useValue: { port: 3000 } }Повертає просте значення чи об'єкт
Фабрика (factory) провайдер{ provide: 'TOKEN', useFactory: () => new Date() }Створює значення динамічно через функцію
Псевдонім (alias) провайдер{ provide: 'Alias', useExisting: UsersService }Робить посилання на вже наявний провайдер
Користувацький клас-провайдер{ provide: 'Logger', useClass: CustomLogger }Дозволяє підмінити реалізацію класу

Приклади різних провайдерів

useValue

javascript
@Module({ providers: [ { provide: 'API_KEY', useValue: '12345' }, ], }) export class AppModule {}

Ін'єкція:

javascript
@Injectable() export class SomeService { constructor(@Inject('API_KEY') private apiKey: string) {} }

useFactory

javascript
@Module({ providers: [ { provide: 'RANDOM_NUMBER', useFactory: () => Math.random(), }, ], }) export class AppModule {}

useClass

javascript
@Injectable() class DefaultLogger { log(msg: string) { console.log('[Default]', msg); } } @Injectable() class CustomLogger { log(msg: string) { console.log('[Custom]', msg); } } @Module({ providers: [ { provide: DefaultLogger, useClass: CustomLogger }, ], }) export class AppModule {}

Тепер усюди, де запитується DefaultLogger, буде використовуватися CustomLogger.

Провайдери та скоуп (Scope)

За замовчуванням провайдер - singleton, але можна змінити область його дії:

javascript
@Injectable({ scope: Scope.REQUEST }) export class RequestScopedService { // створюється заново на кожен HTTP-запит }
ScopeОпис
Default (Singleton)Один екземпляр на весь застосунок
RequestНовий екземпляр для кожного запиту
TransientНовий екземпляр для кожного використання

Де реєструються провайдери

Зазвичай - всередині модуля:

javascript
@Module({ providers: [UsersService], exports: [UsersService], }) export class UsersModule {}

Щоб використати UsersService в іншому модулі:

javascript
@Module({ imports: [UsersModule], }) export class AuthModule {}

Підсумок

ПоняттяОпис
ПровайдерКлас чи значення, кероване DI контейнером NestJS
ПризначенняПостачати функціонал, логіку чи дані іншим частинам застосунку
Основний інструмент@Injectable() і система Dependency Injection
РеєструєтьсяУ секції providers модуля
ТипиuseClass, useValue, useFactory, useExisting

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

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

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