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 в VS Code

Настройка Visual Studio Code используя расширение Debugger for Chrome для отладки Angular приложений
03 декабря 2017 г. в Angular

Angular environment variables

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

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

@Directive v/s @Component in Angular

Компоненты создают DOM элементы и добавляют к ним поведение, а директивы только добавляют поведение к существующим DOM элементам

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

Angular. Когда не надо отписываться в RxJS?

В async pipe за вас отпишется Angular. Во всех остальных случаях лучше отписываться самостоятельно. Допускается не отписываться в потоках, где будет гарантировано вызван complete.