Dependency injection

Вполне вероятна ситуация, когда мы захотим использовать один сервис в другом сервисе. Например, в прошлой теме был создан сервис для работы с данными. Что если нам необходимо логгировать все операции с данными. Для логгирования определим новый сервис. Для этого добавим в папку appновый файл log.service.ts со следующим содержимым:

export class LoggerService { 
  public write(logMessage: string) {
    console.log(logMessage);
  }
}

Для логгирования в сервисе определен методwrite, который выводит некоторое сообщение на консоль.

Теперь используем этот сервис. Для этого изменим код в файле data.service.ts:

@Injectable()
export class DataService {

  private _data: Todo[] = [{
      title: "Todo 1"
    },
    {
      title: "Todo 2"
    },
    {
      title: "Todo 2"
    }
  ];

  constructor(private logService: LogService){}

  getData() {
    this.logService.write("Get Data");    
    return this._data;
  }

  addData(title: string) {  
    this.logService.write("Add Data");   
    this.data.push({
      title
    });
  }
}

Чтобы указать, что сервис сам может использовать другие сервисы, к классу сервиса применяется декоратор @Injectable(). Если класс не будет иметь подобного декоратора, то встроенный механизм внедрения зависимостей не сможет создать объект этого класса и выдаст ошибку.

Существует общая рекомендации от разработчиков Angular применять декоратор @Injectable() к любому классу сервиса, хотя в некоторых ситуациях он не нужен.

Хотя в прошлой теме мы могли использовать сервис в компоненте без применения к компоненту декоратора Injectable. Дело в том, что декоратор Component, который применяется к компоненту, является подтипом Injectable.

И также как в случае с DataService, сервис LogService также надо зарегистрировать в списке провайдеров TodoListComponent:

providers: [DataService, LogService]

Dependency injection - это способ предоставить новый экземпляр класса с полностью сформированными зависимостями, которые он требует. Большинство зависимостей - это сервисы. Angular использует dependency injection для обеспечения новых компонентов необходимыми сервисами.

Angular может определить, какие сервисы нужны компоненту, глядя на типы параметров его конструктора. Например, конструктору вашего TodoListComponentнеобходим сервис DataService:

constructor(private dataService: DataService) { }

Когда Angular создает компонент, он сначала запрашивает injector для служб, которые требуется компоненту.

Injector поддерживает контейнер экземпляров служб, который он ранее создал. Если запрошенный экземпляр службы не находится в контейнере, инжектор делает его и добавляет его в контейнер, прежде чем вернет сервис в Angular. Когда все запрошенные сервисы были зарезолвлены и возвращены, Angular может вызвать конструктор компонента с этими службами в качестве аргументов. Это и есть Dependency injection.

Если injector не имеет нужного сервиса, как он знает, как его создать?

Для избежания этого, мы должны предварительно зарегистрировать provider DataServiceс инжектором. Провайдер создает или возвращает уже существующий экземпляр сервиса.

Мы можете регистрировать provider в компонентах (как делали это выше), то также и в модулях.

Регистрация на уровне компонента означает, что вы получаете новый экземпляр сервиса с каждым новым экземпляром этого компонента.

Если же сервис зарегистрирован в модуле, то все компоненты этого модуля будут получать один и тот же экземпляр сервиса. Это очень важная особенность, с которой мы будем сталкиваться очень часто.

results matching ""

    No results matching ""