Miesięcznik informatyków i menedżerów IT sektora publicznego

Paweł Ziółkowski

Serwisy i zależności w Angularze

W Angularze znajdziemy pomocne rozwiązanie, które ułatwia współdzielenie kodu w aplikacji. Wprowadza ono jednak wiele nowych pojęć i technologii. Omawiamy je, wyjaśniając świat zależności we frameworku.

Generowanie serwisu przez CLI Angular. Zrzut przedstawia wynik działania polecenia, czyli utworzenie wymaganych plików w katalogu data.

Podczas pisania kodu często zdarzy się nam współdzielić jego fragment w kilku miejscach w programie. Fragmentem może być funkcja wykonująca połączenie z bazą danych lub stała wartość jak hasło. Tego rodzaju części kodu możemy wyodrębnić i zamknąć w osobnej klasie, a następnie utworzyć instancję takiej klasy (z wykorzystaniem operatora new) w konstruktorze (więcej na ten temat w artykule „Framework Angular w nowej wersji”, „IT w Administracji” 2019, nr 3) i dostać odpowiednie dane. Poniższy kod prezentuje takie rozwiązanie:

class WysylkaEmail {
private serwisEmail;
constructor() {
this.serwisEmail = new SerwisEmail("hasloDoWysylki");
}
wyslijEmail(tresc: string, adres: string) {
this.serwisEmail.wyslij(tresc, adres);
}
}

Klasa odpowiedzialna za przygotowanie poczty (pośrednik) WysylkaEmail odwołuje się w konstruktorze do klasy dostawcy usług e-mail SerwisEmail, przekazując jej hasło podczas tworzenia instancji. Ta sama klasa fizycznie wysyła wiadomość do wskazanego adresata.

Wstrzykiwanie zależności

Angular dostarcza nam prostsze rozwiązanie do korzystania z innych klas. Zamiast samemu tworzyć instancję SerwisEmail, możemy poprosić o nią w konstruktorze, a specjalny serwis należący do frameworka utworzy dla nas pożądany obiekt. Metoda taka w programowaniu nazywa się odwróceniem kontroli (IoC – Inversion of Control) i polega na przekazaniu wykonania części kodu osobnemu bytowi. Podczas programowania w JavaScripcie spotykaliśmy się już z tym rozwiązaniem, np. przy wywoływaniu funkcji na podstawie określonego zdarzenia – kliknięcia myszką w przycisk. Odwróceniem kontroli było tu uruchomienie funkcji przez zdarzenie, a nie obiekt, w którym definiowano tę funkcję.

Rozwiązanie IoC oferowane przez Angulara nazywa się wstrzykiwaniem zależności (DI – Dependency Injection). Zależnością jest tu używany kod oraz relacja między kodem, który go żąda, a tym, który zostanie mu dostarczony. Dostarczycielem kodu jest usługa – injector. Komunikuje się ona z serwisem Provider za pomocą specjalnego identyfikatora każdej zależności (tzw. token). Tokenem zazwyczaj jest nazwa klasy, o którą prosimy usługę Injector. Przedstawiony wcześniej kod w Angularze będzie teraz wyglądał tak:

class WysylkaEmail {
constructor(private serwisEmail: SerwisEmail) {
}
wyslijEmail(tresc: string, adres: string) {
this.serwisEmail.wyslij(tresc, adres);
}
}

Przenieśliśmy deklarację prywatnego pola SerwisEmail do parametru konstruktora. Nie tworzymy już instancji z wykorzystaniem operatora new. Tworzeniem obiektu zajmie się injector na podstawie tokenu SerwisEmail, a my możemy zastosować jego metodę wyślij.

Provider

Aby dokładniej wyjaśnić działanie DI w Angularze, posłużmy się przykładem, w którym injector będzie dostarczał stałą wartość przez skonfigurowanego przez nas providera. Za pomocą Angular CLI tworzymy nowy projekt w terminalu (polecenie ng new serwis). Po pobraniu wszystkich plików projektu przejdźmy do katalogu app i utwórzmy w nim plik provider-value.ts z kodem:

import { InjectionToken } from '@angular/core';
const wartosc = '0654895156';
export const ID = new InjectionToken<string>('ID');
export const ID_PROVIDER = {
provide: ID,
useValue: wartosc
};

W pierwszej linijce importujemy klasę InjectionToken, która będzie opakowaniem dla naszego identyfikatora wartości – dla tokena zdefiniowanego jako ID w trzeciej linijce kodu. Następnie przypisujemy stałą wartość, którą będziemy serwować innym klasom. Ostatnim elementem jest provider, a zatem zwykły obiekt posiadający dwie właściwości – provide i useValue. Wartość właściwości provide to identyfikator (token), pod którym będzie się kryła wartość z drugiej właściwości, czyli nasza stała wartość. Zarówno token, jak i provider zostały oznaczone słowem kluczowym export, co oznacza, że będą one widoczne na zewnątrz tego pliku, po zaimportowaniu w innych plikach. Otwórzmy plik app.component.ts i dodajmy do niego import elementów, oznaczonych przez export, z wcześniej utworzonego pliku:

import { ID_PROVIDER, ID } from './provider-value';

Do dekoratora @Component dodajemy specjalną właściwość providers, która jest tablicą. W niej umieścimy jedną pozycję z zaimportowanym providerem (obiektem):

providers: [ID_PROVIDER]

[...]

Autor jest absolwentem Uniwersytetu Ekonomicznego we Wrocławiu, pracuje jako informatyk w Urzędzie Gminy w Miękini.

Pełna treść artykułu jest dostępna w papierowym wydaniu pisma. Zapraszamy do składania zamówień na prenumeratę i numery archiwalne.
 
 

Polecamy

Biblioteka Informacja Publiczna

Specjalistyczne publikacje książkowe dla pracowników administracji publicznej

więcej