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)


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

Angular environment variables

Создание и использования переменных окружения в Angular с использованием CLI >= 6 версии.

07 января 2019 г. в Angular

#local variable внутри *ngIf

Представлены 2 варианта решения, как сослаться на локальную переменную шаблона (#myVar) за пределами шаблона:

  • @ViewChild
  • @ViewChildren
12 февраля 2019 г. в Angular

let-* $implicit in Angular template

Синтаксис let-* позволяет объявить переменную в шаблоне , использования ключа $implicit позволяет устанавливать значение по-умолчанию для объявленной переменной.

29 августа 2018 г. в Angular

Angular. Can't set breakpoints in VS Code

Вариант решения проблемы, когда не срабатывают точки остановки при разработке Angular приложений в редакторе VS Code
10 апреля 2018 г. в Angular

RxJs Subjects

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