X-Git-Url: https://juplo.de/gitweb/?a=blobdiff_plain;f=src%2Fapp%2Fhero.service.ts;h=b794b8ad00b27c0a98801cee73a672aeda301a5f;hb=b96b10a45927728a8e0c2234f494fb9eebd3df16;hp=a59d76b34df6adf37ced337d7cc2c32dbfb855eb;hpb=88fd95b95db3ee160af3eb441daaf69a6419c2b7;p=examples%2Fangular-tour-of-heroes diff --git a/src/app/hero.service.ts b/src/app/hero.service.ts index a59d76b..b794b8a 100644 --- a/src/app/hero.service.ts +++ b/src/app/hero.service.ts @@ -1,7 +1,10 @@ import { Injectable } from '@angular/core'; -import { Observable, of } from 'rxjs'; +import { Observable, of, EMPTY } from 'rxjs'; import { Hero } from './hero'; import { HEROES } from './mock-heroes'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { MessageService } from './message.service'; +import { catchError, tap } from 'rxjs/operators'; @Injectable({ @@ -9,9 +12,91 @@ import { HEROES } from './mock-heroes'; }) export class HeroService { - constructor() { } + heroesUrl = 'api/heroes'; // URL to web api + httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }) + }; - getHeroes() : Observable { - return of(HEROES); + constructor( + private http: HttpClient, + private messageService: MessageService) { } + + getHeroes(): Observable { + this.log('fetching heroes...'); + return this.http + .get(this.heroesUrl) + .pipe( + tap((heroes: Hero[]) => this.log(`fetched ${heroes.length} heroes`)), + catchError(this.handleError('getHeroes', [])) + ); + } + + /** POST: add a new hero to the server */ + addHero(hero: Hero): Observable { + return this.http.post(this.heroesUrl, hero, this.httpOptions).pipe( + tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)), + catchError(this.handleError('addHero')) + ); + } + + /** GET hero by id. Will 404 if id not found */ + getHero(id: number): Observable { + this.log(`requested hero id=${id}`); + const url = `${this.heroesUrl}/${id}`; + return this.http.get(url).pipe( + tap(_ => this.log(`fetched hero id=${id}`)), + catchError(this.handleError(`getHero id=${id}`)) + ); + } + + /** PUT: update the hero on the server */ + updateHero(hero: Hero): Observable { + return this.http.put(this.heroesUrl, hero, this.httpOptions).pipe( + tap(_ => this.log(`updated hero id=${hero.id}`)), + catchError(this.handleError('updateHero')) + ); + } + + /* GET heroes whose name contains search term */ + searchHeroes(term: string): Observable { + if (!term.trim()) { + // if not search term, return empty hero array. + return of([]); + } + return this.http.get(`${this.heroesUrl}/?name=${term}`).pipe( + tap(x => x.length ? + this.log(`found heroes matching "${term}"`) : + this.log(`no heroes matching "${term}"`)), + catchError(this.handleError('searchHeroes', [])) + ); + } + + /** + * Handle Http operation that failed. + * Let the app continue. + * @param operation - name of the operation that failed + * @param result - optional value to return as the observable result + */ + private handleError(operation = 'operation', result?: T) { + return (error: any): Observable => { + + // TODO: send the error to remote logging infrastructure + console.error(error); // log to console instead + + // TODO: better job of transforming error for user consumption + this.log(`${operation} failed: ${error.message}`); + + // Let the app keep running by returning an empty result. + if (result === undefined) { + return EMPTY as Observable; + } else { + return of(result as T); + } + }; + } + + /** Log a HeroService message with the MessageService */ + private log(message: string) { + this.messageService.add(`HeroService: ${message}`); } }