freeCodeCamp/guide/russian/angular/services-and-injectors/index.md

16 KiB
Raw Blame History

title localeTitle
Services and Injectors Услуги и инжекторы

Услуги и инжекторы

мотивация

Компоненты отвечают за данные, которые отображаются в шаблоне. Использование внешних сервисов может упростить эту ответственность. Кроме того, инкапсулировать посторонние гораздо проще в обслуживании.

Делегирование слишком большого количества обязанностей на один компонент может усложнить класс компонента. И что, если эти обязанности применяются к нескольким компонентам? Копирование и вставка такой логики - крайне плохая практика. Любые будущие изменения в логике сложнее реализовать и протестировать.

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

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

Что касается тестирования и будущих модификаций, вся логика находится в одном месте. Служба создается из своего источника. Тестирование и модификация источника применяются в любом месте, где вводится служба.

Введение в услуги

Услуга является типом схемы, доступной в Angular. Он генерируется интерфейсом командной строки (CLI): ng generate service [name-of-service] . Замените [name-of-service] на предпочтительное имя. Команда CLI дает следующее.

import { Injectable } from '@angular/core'; 
 
 @Injectable({ 
  providedIn: 'root' 
 }) 
 export class LoggerService { 
  constructor() { } 
 } 

Логика обслуживания различна в своем классе. Угловой интерпретирует класс как инъекционную услугу, основанную на @Injectable decorator. Инъекционные услуги должны регистрироваться инжектором.

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

Поле @Injectable metadata providedIn: 'root' нацеливает корневой модуль текущего приложения ( app.module.ts ). Он регистрирует сервис с помощью инжектора модуля, чтобы он мог внедрить эту услугу в любой из ее дочерних элементов.

Инъекторы являются строительными блоками системы впрыскивания углов. Инъекторы - это хорошее место, чтобы сосредоточить свое внимание, прежде чем продолжать пользоваться услугами.

Форсунки

Приложение, начиная с app.module.ts , содержит иерархию инжекторов. Они существуют вместе с каждым модулем и компонентом в дереве приложений.

Иерархия приложений

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

Службы, зарегистрированные в корне приложения ( app.module.ts ), доступны для всех компонентов. Инжектор для компонента может не иметь зарегистрированной определенной службы. Если это так, и компонент запрашивает его инстанцирование, инжектор отложит его родитель. Эта тенденция сохраняется до тех пор, пока не дойдут до инжектора корня или службы.

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

Внедрение зависимости

Существует несколько способов регистрации службы с помощью инжекторов приложения.

providedIn: 'root' поле providedIn: 'root' метаданных providedIn: 'root' @Injectable обеспечивает наиболее рекомендуемый подход. Это поле метаданных, выпущенное с помощью Angular 6.

Как упоминалось ранее, providedIn: 'root' регистрирует сервис с инжектором корневого модуля. В результате он реализуется во всем приложении.

Новизна providedIn: 'root' - дрожание дерева . Если служба не используется, несмотря на ее регистрацию, она встряхивается от приложения во время выполнения. Таким образом, он не потребляет никаких ресурсов.

Другие два пути более прямые и традиционные. Конечно, они не предлагают дрожание деревьев.

Служба может регистрироваться любым инжектором вдоль дерева компонентов. Вы вставляете эту услугу в качестве поставщика в @Component метаданных @Component : providers: [] . Услуга доступна для компонента и его детей

В третьей стратегии регистрации метаданные providers: [] существуют как свое поле в @NgModule . Услуга является доступной из модуля в базовое дерево компонентов.

Помните, что в отличие от providedIn: 'root' , регистрация @NgModule не предлагает дрожание дерева. Обе стратегии идентичны. Когда служба регистрируется с помощью @NgModule , она потребляет ресурсы, даже если она не используется приложением.

Услуги продолжаются

Далее написание фактического сервиса. Чтобы повторить, службы обрабатывают определенные функции от имени компонентов приложения.

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

Случаи применения

Несколько примеров имеют большое значение для полного понимания сервисов.

  • консольные журналы

  • Запросы API

Оба они распространены в большинстве приложений. Наличие служб для обработки этих операций уменьшит сложность компонентов.

Консольные журналы

Этот пример создается из базового скелета @Injectable . Скелет доступен через выполнение CLI ( ng generate service [name-of-service]] ).

// services/logger.service.ts 
 
 import { Injectable } from '@angular/core'; 
 
 interface LogMessage { 
  message:string; 
  timestamp:Date; 
 } 
 
 @Injectable({ 
  providedIn: 'root' 
 }) 
 export class LoggerService { 
  callStack:LogMessage[] = []; 
 
  constructor() { } 
 
  addLog(message:string):void { 
      // prepend new log to bottom of stack 
      this.callStack = [{ message, timestamp: new Date() }].concat(this.callStack); 
  } 
 
  clear():void { 
      // clear stack 
      this.callStack = []; 
  } 
 
  printHead():void { 
      // print bottom of stack 
      console.log(this.callStack[0] || null); 
  } 
 
  printLog():void { 
      // print bottom to top of stack on screen 
      this.callStack.reverse().forEach((logMessage) => console.log(logMessage)); 
  } 
 
  getLog():LogMessage[] { 
      // return the entire log as an array 
      return this.callStack.reverse(); 
  } 
 } 

LoggerService регистрируется с корневым модулем с помощью @Injectable . Таким образом, он может создавать экземпляр в app.component.html .

// app.component.ts 
 
 import { Component, OnInit } from '@angular/core'; 
 import { LoggerService } from './services/logger.service'; 
 
 @Component({ 
  selector: 'app-root', 
  templateUrl: './app.component.html' 
 }) 
 export class AppComponent implements OnInit { 
  logs:object[] = []; 
 
  constructor(private logger:LoggerService) { } 
 
  updateLog():void { 
      this.logger.printHead(); 
      this.logs = this.logger.getLog(); 
  } 
 
  logMessage(event:any, message:string):void { 
      event.preventDefault(); 
 
      this.logger.addLog(`Message: ${message}`); 
      this.updateLog(); 
  } 
 
  clearLog():void { 
      this.logger.clear(); 
      this.logs = []; 
  } 
 
  ngOnInit():void { 
      this.logger.addLog(View Initialized); 
      this.updateLog(); 
  } 
 } 

Шаблон HTML обеспечивает дальнейшее понимание использования компонентом LoggerService.


<!-- app.component.html --> 
 
 <h1>Log Example</h1> 
 
 <form (submit)="logMessage($event, userInput.value)"> 
  <input #userInput placeholder="Type a message..."> 
  <button type="submit">SUBMIT</button> 
 </form> 
 
 <h3>Complete Log</h3> 
 <button type="button" (click)="clearLog()">CLEAR</button> 
 <ul> 
  <li *ngFor="let log of logs; let i=index">{{ logs.length - i }} > {{ log.message }} @ {{ log.timestamp }}</li> 
 </ul> 

У этого есть ощущение приложения ToDo. Вы можете регистрировать сообщения и очищать журнал сообщений. Представьте себе, если бы вся логика из сервиса была вписана в AppComponent! Это усложнило бы код. LoggerService хранит связанный с журналом код, инкапсулированный из основного класса AppComponent.

Запросы на выборку

Вот еще один пример, который стоит поиграть. Этот пример возможен благодаря JSONPlaceholder 1 typicode . API является общедоступным и бесплатным.

import { Injectable } from '@angular/core'; 
 import { HttpClient } from '@angular/common/http'; 
 import { Observable } from 'rxjs'; 
 
 // https://jsonplaceholder.typicode.com 
 // public API created by typicode @ https://github.com/typicode 
 
 interface Post { 
  userId:number; 
  id:number; 
  title:string; 
  body:string; 
 } 
 
 @Injectable({ 
  providedIn: 'root' 
 }) 
 export class PlaceholderService { 
  constructor(private http:HttpClient) { } 
 
  getPosts():Observable<Post[]> { 
      return this.http.get('https://jsonplaceholder.typicode.com/posts'); 
  } 
 
  getPost(id:number):Observable<Post> { 
      return this.http.get(`https://jsonplaceholder.typicode.com/posts/${id}`); 
  } 
 } 

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

Вывод

Услуги и инъекции зависимости очень полезны вместе. Они позволяют разработчикам инкапсулировать общую логику и внедрять различные компоненты. Это само по себе является огромным удобством для любого будущего обслуживания.

Инъекторы работают в качестве посредников. Они посредничают между компонентами-экземплярами и резервуаром зарегистрированных услуг. Инъекторы предлагают эти впечатляющие услуги своим детям-филиалам.

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

источники

  1. Typicode, JSONPlaceholder , https://jsonplaceholder.typicode.com, доступ к 29 мая 2018 года.

Ресурсы