6: Get Data from a Server
[examples/angular-tour-of-heroes] / src / app / hero.service.ts
index 7e0771a..75a002b 100644 (file)
@@ -1,6 +1,10 @@
 import { Injectable } from '@angular/core';
+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({
@@ -8,9 +12,58 @@ import { HEROES } from './mock-heroes';
 })
 export class HeroService {
 
-  constructor() { }
+  heroesUrl = 'api/heroes';  // URL to web api
 
-  getHeroes() : Hero[] {
-    return HEROES;
+  constructor(
+    private http: HttpClient,
+    private messageService: MessageService) { }
+
+  getHeroes(): Observable<Hero[]> {
+    this.log('fetching heroes...');
+    return this.http
+      .get<Hero[]>(this.heroesUrl)
+      .pipe(
+        tap((heroes: Hero[]) => this.log(`fetched ${heroes.length} heroes`)),
+        catchError(this.handleError<Hero[]>('getHeroes', []))
+      );
+  }
+
+  /** GET hero by id. Will 404 if id not found */
+  getHero(id: number): Observable<Hero> {
+    this.log(`requested hero id=${id}`);
+    const url = `${this.heroesUrl}/${id}`;
+    return this.http.get<Hero>(url).pipe(
+      tap(_ => this.log(`fetched hero id=${id}`)),
+      catchError(this.handleError<Hero>(`getHero id=${id}`))
+    );
+  }
+
+  /**
+   * 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<T>(operation = 'operation', result?: T) {
+    return (error: any): Observable<T> => {
+
+      // 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<T>;
+      } else {
+        return of(result as T);
+      }
+    };
+  }
+
+  /** Log a HeroService message with the MessageService */
+  private log(message: string) {
+    this.messageService.add(`HeroService: ${message}`);
   }
 }