Пояснення кутових послуг та ін'єкції залежностей

Послуги та інжектори

Компоненти відповідають за дані, які відображаються в шаблоні. Наявність зовнішніх служб, які можна використовувати, може спростити цю відповідальність. Плюс до всього, інкапсулювання стороннього набагато легше підтримувати.

Делегування занадто багатьох обов'язків на один компонент може ускладнити клас компонента. А що, якби ці обов'язки поширювались на декілька компонентів? Копіювання та вставка такої логіки є надзвичайно поганою практикою. Будь-які майбутні зміни в логіці буде важче здійснити та перевірити.

Angular мав на меті приборкати цю проблему сервісами та введенням залежностей. Обидві концепції працюють разом, забезпечуючи модульну функціональність.

Компонентам також не потрібно надавати сторонніх відомостей. Послуга імпортує те, що потрібно для функціонування від імені компонентів, які вона обслуговує . Компонентам потрібно лише створити екземпляр служби. Звідти вони обслуговують власні потреби за допомогою екземпляра екземпляра служби.

Що стосується тестування та майбутніх модифікацій, вся логіка в одному місці. Служба створює екземпляри зі свого джерела. Тести та модифікації джерела застосовуються скрізь, де вводиться послуга.

Вступ до послуг

Послуга - це тип схеми, доступний у Angular. Це generatable з допомогою інтерфейсу командного рядка (CLI): ng generate service [name-of-service]. Замініть [name-of-service]бажаною назвою. Команда CLI дає таке.

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

Логіка послуги відрізняється в межах свого класу. Angular інтерпретує клас як ін'єкційну послугу, що базується на @Injectableдекораторі. Ін’єкційні служби повинні реєструватися за допомогою інжектора.

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

Поле @Injectableметаданих providedIn: ‘root’націлено на кореневий модуль поточної програми ( app.module.ts). Він реєструє службу за допомогою інжектора модуля, щоб він міг вколоти цю службу в будь-якого з її дітей.

Інжектори - це будівельні блоки системи впорскування залежностей Angular. Інжектори - це гарне місце, щоб зосередити вашу увагу, перш ніж продовжувати надавати послуги.

Інжектори

Додаток, що починається з app.module.ts, містить ієрархію інжекторів. Вони існують поряд із кожним модулем та компонентом у дереві додатків.

Ієрархія додатків

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

Послуги, зареєстровані в кореневій частині програми ( app.module.ts), доступні для всіх компонентів. Інжектор для компонента може не мати певної служби, зареєстрованої. Якщо це так, і компонент вимагає його створення, інжектор буде переходити до свого батька. Ця тенденція триває до тих пір, поки не буде досягнуто кореневий інжектор або служба не знайдена.

Переглядаючи схему, скажіть, що служба реєструється в інжекторі точки В. Усі компоненти в точці С і вниз не матимуть доступу до послуги, зареєстрованої на інжекторі В. Інжектори ніколи не надаватимуть своїм дітям послуги.

Ін’єкція залежності

Існує кілька способів зареєструвати послугу за допомогою інжекторів програми.

Поле providedIn: ‘root’метаданих @Injectableнадає найбільш рекомендований підхід. Це поле метаданих випущено разом з Angular 6.

Як вже згадувалося раніше, providedIn: ‘root’реєструє службу за допомогою інжектора кореневого модуля. В результаті він може бути встановлений у всьому додатку.

Новизна - providedIn: ‘root’це струшування дерев . Якщо послуга не використовується, незважаючи на реєстрацію, вона витрушується з програми під час виконання. Таким чином він не споживає жодних ресурсів.

Два інших способи є більш прямими і традиційними. Звичайно, вони не пропонують струшування дерев.

Служба може зареєструватися з будь-якою форсункою вздовж дерева компонентів. Ви вставляєте службу в якості постачальника в @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  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.

Log Example

SUBMIT

Complete Log

CLEAR
  • {{ logs.length - i }} > {{ log.message }} @ {{ log.timestamp }}

Це відчуває додаток ToDo. Ви можете реєструвати повідомлення та очищати журнал повідомлень. Уявіть, якби вся логіка сервісу була всунута в AppComponent! Це ускладнило б код. LoggerService зберігає пов'язаний з журналом код, інкапсульований з основного класу AppComponent.

Отримати запити

Here is one more example worth playing around with. This example is possible thanks to typicode’s JSONPlaceholder1. The API is public and free to use.

import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; // //jsonplaceholder.typicode.com // public API created by typicode @ //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 { return this.http.get('//jsonplaceholder.typicode.com/posts'); } getPost(id:number):Observable { return this.http.get(`//jsonplaceholder.typicode.com/posts/${id}`); } }

This is more of a stand-alone piece than a fully fleshed out example. Fetch requests tend to work better as an injectable service. The alternative is an over-complicated component. The injected class subscribes to what the PlaceholderService pre-configures.

Conclusion

Services and dependency injection are very useful together. They allow developers to encapsulate common logic and inject across multiple different components. This alone is a massive convenience for any future maintenance.

Injectors work as intermediaries. They mediate between instantiating components and a reservoir of registered services. Injectors offer these instantiable services to their branch children.

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

Ресурси для Angular

  • Кутова документація
  • Вступ до ін’єкції кутової залежності
  • Що таке ін’єкція залежності та коли її використовувати
  • Кращі приклади кутового коду
  • Angular GitHub Repository
  • Ін’єкція залежності
  • Вступ до послуг та DI