Angular dependency injection

DI — внедрение зависимостей

Provider (Поставщик)

Инжекторы и провайдеры могу конфигурироваться на трех уровнях приложения, путём задания метаданных в декораторах:

  1. @Injectable() - на уровне сервиса.
  2. @NgModule() - на уровен модуля NgModule.
  3. @Component() - на уровне компонента.
  providers: []

Определяется объектом ключ-значение и описывает как зависимость будет предоставлена.

Провайдер класса

  providers: [{
    provide: UserService,   <== ключ (просто строка)
    useClass: UserService   <== класс
  }]

Синтаксический «сахар»

  providers: [UserService]

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

Зависмость от сущности, не являющейся классом. Вместо "прибитой" константы:

const sToken = 'Пирожок';

Используется

import { InjectionToken } from '@angular/core';
...
const sToken = new InjectionToken<string>('блюдо');

Тогда запись зависимости выглядит следующим образом:

  providers: [{
    provide: sToken,     <== ключ 
    useValue: 'Пирожок'  <== значение
  }]

Провайдер «фабрика»

Используется для случая получения сущности по условию.

  providers: [{
    provide: UserService,     <== ключ 
    useFactory: () => {
      if (условие) {
        return new UserServiceA();
      } else {
        return new UserServiceB();
      }
    }
  }]

Множественные провайдеры

Для случая, когда вместо одной зависимости требуется массив используется multi: true. При этом значение не перезаписывают массив, а добавляют в него значения.

...
providers: [
  { provide: sToken, useValue: 'Пирожок', multi: true },
  { provide: sToken, useValue: 'Печенька', multi: true }
]
...
export class AppComponent implements OnInit {
  constructor(
    @Inject(sToken) private _multiProvider,
  ) {}

  ngOnInit() {
    console.log(this._multiProvider); // выведет  ["Пирожок", "Печенька"]
  }  
}

Injector

Механизм разрешающий зависимости и создающий сущности

Инжектор - объект в системе Angular, который может найти зависимость по ключу в своем кеше или создать зависимость с использованием настроенного провайдера (Provider). Инжекторы создаются для NgModules автоматически как часть процесса начальной загрузки и наследуются через иерархию компонентов.

Работа с инжектором вручную.

const injector = ReflectiveInjector.resolveAndCreate([UserService, { provide: sToken, useValue: 'Печенька'}]);
const cookie = injector.get(sToken); 
const _uService = injector.get(UserService);

Dependency

Внедряемая зависимость

Обычно класс или константа. Тут всё просто - сущность, которую необходимо внедрить.

Зависимость Angular достаёт из декораторов @Component, @Pipe, @Directive, @Inject, @Injectable.

Объявление зависимости

export class AppComponent implements OnInit {
  constructor(private _uService: UserService) {} <== Зависимость от UserService

  ngOnInit() {
    this._uService.init();
  }
}

@Inject

Наиболее известна запись зависимости:

constructor(private _uService: UserService) {}

Она эквивалентна:

constructor(@Inject(UserService) private _uService) {}

То есть имеется возможность вручную указать подставляемый ключ.
Этот декоратор используется когда создаётся InjectionToken, потому что он не имеет специфичного тип (см. пример выше про блюдо, string)


Похожие записи

RxJs Subjects

Выдержки из доклада Андрея Алексеева (Tinkoff) про RxJs (Subject, Behaviour Subject, Replay Subject, Async Subject). Применение в Angular.

Вставить <script> в Angular компонент

Добавление сторонних скриптов в Angular по запросу. Как известно, добавить скрипт через шаблон невозможно. Представлено решение как это сделать программно.