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 Pipeable Operators

Начиная с версии rxjs 5.5 операторы вместо цепочки вызовов применяются как параметры функции pipe.

let-* $implicit in Angular template

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

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