Szögszolgáltatások és függőségi injekció magyarázata

Szolgáltatások és injektorok

Az összetevők felelősek a sablonban megjelenő adatokért. Ha külső szolgálatok vesznek igénybe, ez a felelősség leegyszerűsödhet. Ráadásul az idegen beágyazását sokkal könnyebb fenntartani.

Túl sok felelősség átruházása egyetlen komponensre bonyolultabbá teheti az alkatrészosztályt. És mi lenne, ha ezek a felelősségek több összetevőre vonatkoznának? Az ilyen logika másolása és beillesztése rendkívül gyenge gyakorlat. A jövőbeli logikai változásokat nehezebb megvalósítani és tesztelni.

A szögletes ennek a kérdésnek a megfékezését jelentette szolgáltatásokkal és függőség-injektálással. Mindkét koncepció együttesen biztosítja a moduláris funkcionalitást.

Az alkatrészeknek sem kell semmilyen idegen információt megadniuk. A szolgáltatás import mit kell funkciója nevében az elemeket, szolgáltatások . Az összetevőknek csak a szolgáltatást kell példányosítaniuk. Innentől kezdve kiszolgálják saját igényeiket a példányos szolgáltatási példánnyal.

Ami a tesztelést és a jövőbeli módosítást illeti, az összes logika egy helyen van. A szolgáltatás a forrásából származik. A tesztek és a forrás módosításai bárhol érvényesek a szolgáltatásba.

Bevezetés a szolgáltatásokba

A szolgáltatás az Angularban elérhető vázlattípus. Ez generálható a parancssori felület (CLI): ng generate service [name-of-service]. Cserélje [name-of-service]ki egy előnyben részesített névre. A CLI parancs a következőket eredményezi.

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

A szolgáltatás logikája osztályában különbözik. A Angular egy osztályt injektálható szolgáltatásként értelmez a @Injectabledekoratőrtől függetlenül. Az injekciós szolgáltatásoknak regisztrálniuk kell magukat az injektoroknál.

Az összetevő szolgáltatásot nyújt, míg az injektor biztosítja ezt a példányt. Olvassa el a következő részt, hogy többet tudjon meg az injektorokról.

A @Injectablemetaadat mező providedIn: ‘root’az aktuális alkalmazás gyökérmodulját ( app.module.ts) célozza meg . Regisztrálja a szolgáltatást a modul injektorán, hogy bármelyik gyermekébe be tudja adni a szolgáltatást.

Az injektorok az Angular függőség-befecskendező rendszerének építőkövei. Az injektorok alkalmasak arra, hogy figyelmét összpontosítsák, mielőtt tovább folytatnák a szolgáltatásokat.

Injektorok

A kezdő alkalmazás app.module.tsaz injektorok hierarchiáját tartalmazza. Az alkalmazásfa minden modulja és összetevője mellett léteznek.

Alkalmazás hierarchia

A zöld körök jelzik az injektorokat. Szolgáltatási példányokat nyújtanak az alkatrészek példányosításához. Attól függően, hogy egy szolgáltató melyik injektornál van regisztrálva, lehet, hogy nem elérhető egy alkatrész számára.

Az alkalmazás gyökérkönyvtárában regisztrált szolgáltatások ( app.module.ts) minden komponens számára elérhetőek. Előfordulhat, hogy egy alkatrész injektora nem rendelkezik bizonyos szolgáltatásokkal. Ha ez az eset áll fenn, és az alkatrész kéri azonnali elkészítését, az injektor elhalasztja a szülőjét. Ez a tendencia addig tart, amíg el nem éri a gyökérinjektort, vagy meg nem találja a szolgáltatást.

A diagramot nézve mondjuk, hogy egy szolgáltatás regisztrál a B pont injektoránál. A C és a le pont összes alkatrésze nem lesz képes hozzáférni a B injektoránál regisztrált szolgáltatáshoz. Az injektorok soha nem halasztják el gyermekeiket egy szolgáltatási példányért.

Függőségi injekció

Többféle módon regisztrálhatja a szolgáltatást egy alkalmazás injektoraival.

A providedIn: ‘root’metaadat mező a @Injectablelegajánlottabb megközelítést biztosítja. Ez a metaadatmező az Angular 6 kiadásával készült.

Mint korábban említettük, providedIn: ‘root’regisztrál egy szolgáltatást a root modul injektoránál. Ennek eredményeként azonnal elérhető az egész alkalmazásban.

Az újdonság providedIn: ‘root’az, fa-rázás . Ha a szolgáltatás a regisztráció ellenére nincs használatban , futás közben megrázkódik az alkalmazásból. Így nem fogyaszt semmilyen forrást.

A másik két módszer közvetlenebb és hagyományosabb. Igaz, nem kínálnak farázást.

Egy szolgáltatás regisztrálhat bármelyik injektorral az alkatrészfa mentén. Behelyezi a szolgáltatást a szolgáltató a @Componentmetaadat mező: providers: []. A szolgáltatás elérhető az alkatrész és gyermekei számára

A harmadik regisztrációs stratégiában a providers: []metaadatok saját mezőként léteznek a @NgModuledekorátorban. A szolgáltatás a modultól az alapul szolgáló komponens fáig azonnal elérhető.

Ne feledje, hogy ellentétben azzal providedIn: ‘root’, @NgModuleregisztráció nem kínál fa-rázás. Mindkét stratégia egyébként azonos. Miután a szolgáltatás regisztrált a @NgModule(z) webhelyen, akkor is fogyaszt erőforrásokat, még akkor is, ha az alkalmazás fel nem használja.

Szolgáltatások folytatása

A tényleges szolgáltatás megírása következik. Összefoglalva: a szolgáltatások bizonyos funkciókat az alkalmazás összetevői nevében kezelnek.

A szolgáltatások kiválóak a közös műveletek kezelésében. Ezzel megkímélik az alkatrészek felelősségét. Időt takarít meg, ha nem kell újraírni a közös műveleteket több összetevőből. Ez azért is tesztelhetőbb, mert a kód egy helyen van. A változásoknak csak egy helyen kell megtörténniük, anélkül, hogy másutt kellene keresniük.

Használjon tokokat

Néhány példa nagyban hozzájárul a szolgáltatások teljes megértéséhez.

  • konzol naplók
  • API kérések

Mindkettő gyakori a legtöbb alkalmazásban. Ha ezeknek a műveleteknek a kezeléséhez szükséges szolgáltatások vannak, az összetettség összetettebbé válik.

Konzolnaplók

Ez a példa az alapvázból épül fel @Injectable. A csontváz a CLI ( ng generate service [name-of-service]]) végrehajtásával érhető el .

// 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(); } }

A LoggerService regisztrál a gyökérmodulon a @Injectablemetaadatokon keresztül . Így példaképpé válhat a 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(); } }

A HTML sablon további betekintést nyújt a komponens LoggerService használatába.

Log Example

SUBMIT

Complete Log

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

Ez egy ToDo alkalmazás érzését kelti. Naplózhatja az üzeneteket és törölheti az üzenetek naplóját. Képzelje el, ha a szolgáltatás minden logikája belemerült az AppComponent-ba! Bonyolította volna a kódot. A LoggerService megőrzi a naplóhoz kapcsolódó kódot az AppComponent alaposztályból.

Kérések lekérése

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.

A szolgáltatásokról és a függőség-injektálásról további információkat a következő linkeken talál.

Források az Angular számára

  • Szögletes dokumentáció
  • A szögfüggőség injekciójának bevezetése
  • Mi a függőségi injekció és mikor kell alkalmazni
  • A legjobb szögletes kód példák
  • Szögletes GitHub-tár
  • Függőségi injekció
  • Bevezetés a szolgáltatásokhoz és a DI-hez