Skip to main content

Що робить IoC-контейнер в NestJS?

Що таке IoC-контейнер в NestJS

IoC-контейнер (Inversion of Control Container) в NestJS - це механізм, який керує створенням, зберіганням і впровадженням залежностей (провайдерів) у застосунку. Він реалізує принцип Inversion of Control - тобто інверсію управління: → ти не створюєш об'єкти вручну, а доручаєш це фреймворку.

Простими словами

Без IoC-контейнера ти писав би так:

javascript
const usersService = new UsersService(); const usersController = new UsersController(usersService);

З IoC-контейнером Nest робить це автоматично: достатньо вказати залежності в конструкторі:

javascript
@Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) {} }

Nest сам:

  1. створює екземпляр UsersService;
  2. зберігає його в DI-контейнері;
  3. впроваджує його в UsersController.

Як працює IoC-контейнер покроково

  1. Сканує модулі (@Module()) і збирає список усіх providers, controllers і imports.
  2. Реєструє провайдери в контейнері (за токеном - зазвичай це сам клас чи рядковий ідентифікатор).
  3. Створює екземпляри провайдерів (за замовчуванням - один спільний екземпляр, Singleton).
  4. Відстежує залежності і впроваджує їх при створенні інших класів.
  5. Зберігає посилання на вже створені екземпляри, щоб перевикористовувати їх при повторних запитах.

Приклад наочно

javascript
@Injectable() export class UsersService { findAll() { return ['John', 'Alex']; } } @Controller('users') export class UsersController { constructor(private usersService: UsersService) {} @Get() getUsers() { return this.usersService.findAll(); } } @Module({ controllers: [UsersController], providers: [UsersService], }) export class UsersModule {}

Що робить IoC-контейнер:

  1. Бачить UsersModule.
  2. Реєструє UsersService як провайдер.
  3. Створює екземпляр UsersService і зберігає його.
  4. При створенні UsersController бачить, що в конструкторі потрібен UsersService.
  5. Впроваджує (інжектує) готовий екземпляр.

Ключова ідея - інверсія управління

Зазвичай:

Ти створюєш залежності вручну.

З IoC:

Ти просто оголошуєш, що тобі потрібно - контейнер сам вирішує, як це створити.

Переваги IoC-контейнера в NestJS

ПеревагаПояснення
Послаблена зв'язаністьКласи не залежать напряму від реалізації залежностей.
ПеревикористанняОдин екземпляр провайдера можна використовувати в багатьох місцях.
Легке тестуванняМожна підмінити залежності моками.
Автоматичне керування життєвим цикломNest сам створює, кешує й знищує екземпляри.
ГнучкістьМожна перевизначати провайдери (useClass, useValue, useFactory).

Внутрішні деталі (якщо цікаво)

  • Кожен модуль має свій IoC-контейнер (власну область видимості).
  • Контейнери можуть успадковувати залежності з імпортованих модулів.
  • При пошуку залежності Nest йде "вгору по дереву модулів", поки не знайде потрібний провайдер.

Приклад з токенами й фабриками

javascript
@Module({ providers: [ { provide: 'RANDOM', useFactory: () => Math.random(), }, ], }) export class AppModule {} @Injectable() export class ExampleService { constructor(@Inject('RANDOM') private random: number) {} log() { console.log(this.random); } }

IoC-контейнер:

  • реєструє 'RANDOM' як токен;
  • викликає фабрику useFactory;
  • зберігає результат;
  • при створенні ExampleService впроваджує значення random.

Візуальна схема роботи IoC

javascript
┌────────────────────┐ │ @Module()│ imports, providers │ └───────┬────────────┘ ┌──────────────────────────┐ IoC-контейнер NestJS- Реєструє провайдери │ - Створює екземпляри │ - Керує залежностями │ └───────────┬──────────────┘ ┌────────────────────────┐ │ Контролер / Сервіс │ │ → отримує залежності │ │ через конструктор │ └────────────────────────┘

Підсумок

ТермінПояснення
IoC-контейнерСистема, що керує залежностями (Dependency Injection)
ЗавданняСтворювати, зберігати й впроваджувати провайдери
ПринципІнверсія управління: об'єкт не створює залежності сам
ПеревагиПослаблена зв'язаність, перевикористання, тестованість

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

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

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