Pochopení Angular Route Resolverů

winding-road-between-forest

Vývoj reálné aplikace s více voláními na server může být plný chyb. Pokud jste zde, znamená to, že jste se potýkali se zpožděním volání API. Tato zpoždění mohou způsobit negativní UX. Dnes budeme rozumět Route Resolverům v Angularu 8. Existuje několik různých věcí, které můžeme udělat pro zlepšení uživatelského zážitku, například zobrazení indikátoru průběhu. Abychom se drželi tématu, podíváme se, co je Route Resolver a čeho s ním můžeme dosáhnout.

Co je Angular Route Resolver?

Resolver je třída, která implementuje rozhraní Resolve Angular Router. Resolver je vlastně služba, která musí být v kořenovém modulu. V podstatě se Resolver chová jako middleware, který může být spuštěn před načtením komponenty.

Mohlo by se vám také líbit: Angular Resolvery.

Proč v Angularu používat Route Resolvery?

Pro vysvětlení, jak lze v Angularu použít resolver, si představme scénář, kdy používáte *ngIf="some condition" a vaše logika závisí na délce pole, se kterým se manipuluje po dokončení volání API. Například můžete chtít v komponentě zobrazit položky tohoto pole, které byly právě načteny v neuspořádaném seznamu.

<ul><li *ngFor="let item of items">{{item.description}}</li></ul>

V této situaci se můžete dostat do problému, protože vaše data se objeví až po dokončení komponenty. Položky v poli ještě ve skutečnosti neexistují. Zde se hodí nástroj Route Resolver. Třída Angular Route Resolver načte vaše data dříve, než je komponenta připravena. Vaše podmíněné příkazy budou s Resolverem fungovat bez problémů.

Resolve Interface

Než začneme implementovat Route Resolver, podívejme se nejprve, jak vypadá rozhraní Resolve.

export interface Resolve<T> { resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T> | Promise<T> | T { return 'Data resolved here...' }}

Pokud chcete vytvořit Route Resolver, musíte vytvořit novou třídu, která bude implementovat výše uvedené rozhraní. Toto rozhraní nám poskytuje funkci resolve, která v případě potřeby získá dva parametry. Prvním z nich je trasa, která je typu ActivatedRouteSnapshot, a druhým je stav typu RouterStateSnapshot. Zde můžete provést volání API, které získá potřebná data před načtením komponenty.

Pomocí parametru route můžete získat parametry trasy, které mohou být použity ve volání API. Metoda resolve může vrátit Observable, slib nebo jen vlastní typ.

Poznámka: Je důležité zmínit, že prostřednictvím této metody budou vrácena pouze vyřešená data.

To je chyba, kterou udělá spousta lidí, když používají resolvery poprvé! Proto je třeba je před odesláním ve směrovači doplnit.

Odesílání dat do směrovače prostřednictvím resolveru

Ukážu vám, co mám na mysli ve výše uvedené části. Řekněme, že máte metodu, která vrací pozorovatelné:

items: any = ;getData(): Observable<any> { const observable = Observable.create(observer => { observer.next(this.items) }); return observable;}

Takže nyní uvidíte, že odběr, který máme, nikdy nenarazí. To je způsobeno tím, že neposíláte data správně. Nejste dokončili odběr. Chcete-li tuto chybu odstranit, musíte odběr dokončit přidáním dalšího řádku kódu.

observer.complete();

V případě, že vracíte slib, musíte jej před odesláním dat do směrovače vyřešit.

Implementace Route Resolveru

Poté, co jsme skončili se základním vysvětlením a proč a jak používat route resolver, začněme jej implementovat. V tomto krátkém příkladu předpokládám, že jste obeznámeni s příkazy CLI modulu Angular a s tím, jak vytvořit nový projekt, takže budu demonstrovat pouze povinný kód. Demonstrační projekt najdete prostřednictvím repozitáře GitHub na konci článku.

V tomto příkladu budu používat jsonplaceholder jako falešné API pro načítání uživatelských dat, abych demonstroval volání API pomocí route resolverů.

Nejprve budeme potřebovat službu, která pro nás bude načítat uživatelská data. V této službě máme funkci s názvem getUsers(), která vrací pozorovatelný objekt.

@Injectable({providedIn: 'root'})export class FakeApiService { constructor(private http: HttpClient) { } private usersEndpoint = "https://jsonplaceholder.typicode.com/users"; getUsers(): Observable<any> { // We do not subscribe here! We let the resolver take care of that... return this.http.get(this.usersEndpoint); }}

Je důležité, abychom se nepřihlásili k funkci getUsers. O to se postará resolver trasy s názvem UserResolver. Dalším krokem je vytvoření nové služby UserResolver, která bude implementovat funkci resolve rozhraní Resolve směrovače.

@Injectable({providedIn: 'root'})export class UserResolverService implements Resolve<any> { constructor(private fakeApi: FakeApiService) { } resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { return this.fakeApi.getUsers().pipe( catchError((error) => { return empty(); }); ); }}

Tato služba, UserResolver, se automaticky přihlásí k odběru getUsers observable a poskytne směrovači získaná data. V případě chyby lze při načítání dat odeslat prázdnou observable a směrovač nebude pokračovat v cestě.

Navigace bude v tomto okamžiku ukončena. Tímto posledním krokem je vytvoření komponenty, která bude zavolána, když uživatel přejde na trasu /users. Obvykle bez nástroje Resolver budete muset načíst data na háčku ngOnInit komponenty a zpracovat chyby způsobené tím, že „žádná data“ neexistují. Uživatelská komponenta je jednoduchá. Pouze získá data uživatele z ActivatedRoute a zobrazí je do neuspořádaného seznamu.

Po vytvoření komponenty uživatele je třeba definovat trasy a říci směrovači, aby použil resolver ( UserResolver). Toho lze dosáhnout pomocí následujícího kódu do app-routing.modulte.ts.

const routes: Routes = ;@NgModule({ imports: , exports: })export class AppRoutingModule { }

Je třeba nastavit vlastnost resolve do uživatelské trasy a deklarovat UserResolver. Data budou předána do objektu s vlastností users. Poté jste téměř hotovi. Zbývá už jen jedna věc, kterou musíte udělat. Získaná data musíte dostat do komponenty users prostřednictvím ActivatedRoute pomocí následujícího kódu:

constructor(private activatedRoute: ActivatedRoute) { }users: any;ngOnInit() { this.activatedRoute.data.subscribe((data: { users: any }) => { this.users = data.users; });}

Poté je můžete jednoduše zobrazit do HTML bez příkazů *ngIf ( *ngIf="users && users.length > 0 ), protože data tam budou ještě před načtením komponenty.

<h2>Fetched Users:</h2><ul><li *ngFor="let user of users">{{ user.name }}</li></ul>

Shrnutí

Závěrem tohoto článku o Route Resolverech bych rád ještě jednou poukázal na výhody, které nám poskytují. Především se vyhneme otravným kontrolám, které se musí provádět na úrovni HTML, takže nemáme problémy, dokud naše data nepřijmeme. Za druhé nám umožňují více se soustředit na uživatelské prostředí, protože můžeme zastavit navigaci, pokud při jejich načítání dojde k chybě dat, aniž bychom museli načítat komponentu náhledu. Před dokončením navigace můžeme také provádět další činnosti, například připojovat další logiku nebo mapovat data před přístupem k načtené komponentě.

Demonstrační kód je k dispozici na GitHubu.

Další čtení

  • Výukový program Angular: Angular 7 a framework RESTEasy.
  • Vytvoření aplikace Angular 5 krok za krokem.
  • Aplikace Angular 7 + Spring Boot: Příklad Hello World.

Napsat komentář