Angular: Dependency Injection

Что такое DI?

Dependency Injection — паттерн проектирования, при котором класс запрашивает зависимости из внешних источников, а не создаёт их сам. Angular имеет собственный DI-фреймворк для разрешения зависимостей (сервисов и объектов). DI — реализация концепции IoC (Inversion of Control).


Иерархические инжекторы

  • ModuleInjector — настраивается на уровне модуля через @NgModule() или @Injectable().
  • NodeInjector — создаётся неявно на каждом DOM-элементе. По умолчанию пуст, пока не настроен через providers в @Directive() или @Component().

Модификаторы разрешения (Resolution Modifiers)

  • @SkipSelf() — пропускает свой инжектор, начинает с родительского.
  • @Self() — ищет только в собственном инжекторе компонента.
  • @Host() — граница поиска — родительский (host) компонент.
  • @Optional() — возвращает null вместо ошибки, если провайдер не найден.

providers vs viewProviders

  • providers — сервис доступен компоненту, всем дочерним компонентам, включая спроецированные через ng-content.
  • viewProviders — ограничивает провайдер компонентом и его view-детьми; проецируемый через ng-content контент провайдер не видит (можно сделать сервис «приватным»).

NgModule providers стоит избегать — они не tree-shakable. Обычно регистрируются в корневом инжекторе (исключение — lazy-модули).


Синтаксис провайдеров

providers: [{ provide: MyService, useClass: MyService, multi: false }];
  • useClass
  • useValue
  • useFactory + deps
  • useExisting — алиас на существующий сервис

InjectionToken — для простых значений (даты, числа, строки) или бесформенных объектов (массивы, функции).

multi: true — регистрирует несколько сервисов/значений под одним токеном, возвращает массив. Без multi последний провайдер перезаписал бы предыдущий.


@Injectable({ providedIn })

  • root — единый экземпляр в корневом инжекторе (синглтон приложения)
  • platform — общий для всех Angular-приложений в одном окне
  • any — отдельный экземпляр в каждом инжекторе, который запрашивает токен (в частности, свой инстанс в каждом lazy-модуле)
  • конкретный модуль — экземпляр создаётся в инжекторе этого модуля