Провайдеры Angular

Apr 14, 2018

Провайдеры - классы, создающие объекты тогда, когда Angular впервые сталкивается с потребностью разрешить зависимость.

В самом простом случае провайдеры создают экземпляр класса, но есть провайдеры, которые настраивают процесс создания и конфигурации объектов служб.

Обычно провайдеры определяются в свойстве providers декоратора @NgModule (также их можно определять в компонентах и директивах).

Провайдеры

Angular предоставляет разных провайдеров, которые создают объекты разными способами, таким образом мы можем управлять процессом создания служб.

  • Провайдер класса - настраивается при помощи класса, зависимости разрешаются от экземпляра класса.
  • Провайдер значения - настраивается при помощи объекта, зависимости разрешаются от объекта.
  • Провайдер фабрики - настраивается при помощи функции, зависимости разрешаются от объекта, который создается вызовом функции.
  • Провайдер существующий службы - настраивается при помощи имени другой службы, позволяет создавать псевдонимы служб.

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

providers: [{ provide: tester, useClass: "MyService" }],

Свойства провайдера класса:

  • provide - маркер/token
  • useClass - класс от которого создается экземпляр для разрешения зависимостей

Angular сопоставляет провайдеров для классов, но для других типов маркеров потребуется дополнительные действия:

constructor(@Inject('tester') private tester: MyService) {
//...

Декоратор @Inject определяет маркер провайдера для разрешения зависимостей.

или

providers: [MyService],

Класс InjectionToken

Класс OpaqueToken deprecated. Вместо класса OpaqueToken используется InjectionToken - используется для создания уникальных маркеров.

import { Injectable, InjectionToken } from "@angular/core";
export const LOG_SERVICE = new InjectionToken("logger");

"logger" - это строковое значение, которое идентифицирует службу, но маркером становится экземпляр InjectionToken.

Регистрируем в модуле:

providers: [DiscountService, { provide: LOG_SERVICE, useValue: "LogService" }],

Объявляем зависимость при помощи InjectionToken:

constructor(@Inject(LOG_SERVICE) private logger: LogService) {
//...

Провайдер значения

Провайдер значения на angular.io

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

export function SilentLoggerFn() {}

const silentLogger = {
    logs: ['Silent logger says "Shhhhh!". Provided via "useValue"'],
    log: SilentLoggerFn
};
[{ provide: Logger, useValue: silentLogger }]
    

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

Провайдер фабрики использует функцию для создания объекта, который в свою очередь используется для разрешения зависимостей.

Свойства провайдера фабрики

  • provide - задает маркер службы
  • deps - задает массив маркеров провайдеров, котороые будут разрешены и переданы функции, определенной в свойстве <сщву>useFactory. Свойство deps позволяет создавать зависимости от других служб.
  • useFactory - задает функцию, которая определяет объект службы. Объекты, полученные в результате разрешения маркеров свойства <сщву>deps, будут переданы в функцию как аргументы. Результат функции и есть объект, который используется для разрешения зависимостей.

factory-providers на angular.io

let heroServiceFactory = (logger: Logger, userService: UserService) => {
    return new HeroService(logger, userService.user.isAuthorized);
};
export let heroServiceProvider = {
    provide: HeroService,
    useFactory: heroServiceFactory,
    deps: [Logger, UserService]
};

Инжекторы и как они разрешаются

Создавая новый экземпляр класса Angular разрешает зависимости при помощи инжекторов. Существует иерархия инжекторов соответствующая дереву компонентов и директив в приложении. У каждого компонента и директивы свой собственный инжектор. Для каждого инжектора можно настроить свой собственный набор провайдеров - это так называемые локальные провайдеры. Зависимости в Angular разрешаются путем использования ближайшего инжектора компонента или директивы.

Таким образом мы можем установить локального провайдера для директивы (selector: "div") и этот провайдер будет разрешен в соответствующем pipe (у дочернего элемента по отношению к div), у которого используется соответствующая зависимость.

Добавить комментарий