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

258 lines
16 KiB
Markdown
Raw Normal View History

2018-10-12 20:00:59 +00:00
---
title: Services and Injectors
localeTitle: Услуги и инжекторы
---
# Услуги и инжекторы
#### мотивация
Компоненты отвечают за данные, которые отображаются в шаблоне. Использование внешних _сервисов_ может упростить эту ответственность. Кроме того, инкапсулировать посторонние гораздо проще в обслуживании.
Делегирование слишком большого количества обязанностей на один компонент может усложнить класс компонента. И что, если эти обязанности применяются к нескольким компонентам? Копирование и вставка такой логики - крайне плохая практика. Любые будущие изменения в логике сложнее реализовать и протестировать.
Угловое средство предназначено для ограничения этой проблемы с помощью услуг и инъекций зависимостей. Обе концепции работают вместе, чтобы обеспечить одульную_ функциональность.
Компонентам также не нужно предоставлять какую-либо постороннюю информацию. Услуги импортируют то, что ему нужно для работы от имени компонентов, которые он _обслуживает_ . Компонентам требуется только создать экземпляр службы. Оттуда они _обслуживают_ свои собственные потребности с экземпляром экземпляра службы.
Что касается тестирования и будущих модификаций, вся логика находится в одном месте. Служба создается из своего источника. Тестирование и модификация источника применяются в любом месте, где вводится служба.
#### Введение в услуги
Услуга является типом _схемы,_ доступной в Angular. Он генерируется интерфейсом командной строки (CLI): `ng generate service [name-of-service]` . Замените `[name-of-service]` на предпочтительное имя. Команда CLI дает следующее.
```typescript
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LoggerService {
constructor() { }
}
```
Логика обслуживания различна в своем классе. Угловой интерпретирует класс как _инъекционную_ услугу, основанную на `@Injectable` decorator. Инъекционные услуги должны _регистрироваться_ инжектором.
Компонент создает экземпляр службы, в то время как инжектор предоставляет этот экземпляр. Продолжайте читать в следующем разделе, чтобы узнать больше о форсунках.
Поле `@Injectable` metadata `providedIn: 'root'` нацеливает корневой модуль текущего приложения ( `app.module.ts` ). Он регистрирует сервис с помощью инжектора модуля, чтобы он мог _внедрить_ эту услугу в любой из ее дочерних элементов.
Инъекторы являются строительными блоками системы впрыскивания углов. Инъекторы - это хорошее место, чтобы сосредоточить свое внимание, прежде чем продолжать пользоваться услугами.
#### Форсунки
Приложение, начиная с `app.module.ts` , содержит иерархию инжекторов. Они существуют вместе с каждым модулем и компонентом в дереве приложений.
![Иерархия приложений](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image5.png)
Зеленые круги обозначают форсунки. Они предоставляют экземпляры службы для создания компонентов. В зависимости от того, какой инжектор зарегистрирован, он может или не может быть доступен для компонента.
Службы, зарегистрированные в корне приложения ( `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]]` ).
```typescript
// 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` .
```typescript
// 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.
```html
<!-- 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](https://jsonplaceholder.typicode.com) . API является общедоступным и бесплатным.
```typescript
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 года.](https://jsonplaceholder.typicode.com)
## Ресурсы
* [Угловая документация](https://angular.io/docs)
* [Угловой репозиторий GitHub](https://github.com/angular/angular)
* [Внедрение зависимости](https://angular.io/guide/dependency-injection-pattern)
* [Введение в службы и DI](https://angular.io/guide/architecture-services)