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 }];useClassuseValueuseFactory+depsuseExisting— алиас на существующий сервис
InjectionToken — для простых значений (даты, числа, строки) или бесформенных объектов (массивы, функции).
multi: true — регистрирует несколько сервисов/значений под одним токеном, возвращает массив. Без multi последний провайдер перезаписал бы предыдущий.
@Injectable({ providedIn })
root— единый экземпляр в корневом инжекторе (синглтон приложения)platform— общий для всех Angular-приложений в одном окнеany— отдельный экземпляр в каждом инжекторе, который запрашивает токен (в частности, свой инстанс в каждом lazy-модуле)- конкретный модуль — экземпляр создаётся в инжекторе этого модуля