Angular2 - HTTP

我们将用HTTPClient来添加一些数据持久化特效。

我们需要在App中启用HTTP服务,HttpClient是Angular通过http 与远程服务器通讯的机制。如果我们需要在整个App中使用并不需要重复导入。我们需要在AppModule顶层中从@angular/common/http 导入HttpClientModule 符号.

import { HttpClientModule } from '@angular/common/http'

并在加入@NgModule.imports 数组中。我们将可以在其他的Services中使用。并不需要重复导入。

给service创建一个从服务器获取数据的方法。

getHeroes(): Observable<object> {
  return this.http.get('http://localhost:8080/findByList/1', {
     headers: new HttpHeaders().set('Access-Control-Allow-Origin','*')
   });
}

 

我需要从服务器获取英雄列表,并返回Component显示。

在使用http的时候我们可以看到HttpClient 带有很多调用方式,Get , Post , Postion , Put , Delete 等。我们可以选择合适的方式调用API,常用的Get , Post。

 

在我们获取数据的时候。我们可能会遇到一些跨域,或者需要发送认证给客户端以便通过服务器认证。我们可以把这些消息写进heades中。

由于远程服务器不会马上应答或者得到服务器的结果。那么我们在Component中。使用结果就会由于异步原因而获取不到结果。所以我们需要告诉返回Observable 模式告诉Component , 当获取到服务器返回结果之后再做处理。

getHeroes(): Observable<Hero[]> {
  return this.http.get<Hero[]>('http://localhost:8080/findByList/1', {
     headers: new HttpHeaders().set('Access-Control-Allow-Origin','*')
   });
}

此方法会返回一个可广场的对象。只有再Component订阅此方法。方法才会执行,并在subscribe中处理返回结果。

//Component 中调用方式
this
.heroesService.getHeroes() .subscribe(her => this.heroes = her);

当service没有返回数据或者不需要处理任何数据时。你只需要显示调subscribe即可

this.heroesService.getHeroes().subscribe();

 

可能有些人对Observable会感到陌生。RxJs也提供另一种方式Promise , 我们可以在 rxjs/operaters/toPromise中导入,并使用

getHeroes(): Promise<Hero[]> {
  return this.http.get('http://localhost:8080/findByList/1', {
     headers: new HttpHeaders().set('Access-Control-Allow-Origin','*')
   }).toPromise().then((response) = > {
    console.log(response);//输出response
  })
; }

当我们在Component中调用getHeroes() 方法我们就可以在then中处理返回结果。

当然任何程序都有可能出现各种问题。特别是从远程服务器获取数据的时候。我们的方法应该捕获数据并做适当的处理。

要捕获错误。我们需要使用RxJS的catchError() 操作符来简历对Observable或者Primise的处理管道pipe。

import { catchError, map, tap } from 'rxjs/operators';

现在我们就可以使用pipe扩展Observable的结果。并给他一个catchError操作符。

getHeroes (): Observable<Hero[]> {
  return this.http.get<Hero[]>(this.heroesUrl)
    .pipe(
      catchError(this.handleError('getHeroes', []))
    );
}

catchError() 操作符拦截失败的Observable,并把错误传给错误处理对象。所以我们把错误交给handleError。handleError(错误处理器)会处理这个错误。并返回一个无害的结果。以便应用能正常工作。

由于所有的HeroService方法都需要共享handleError方法。所以我们需要通用化错误处理器并且支持不同的需求。

/**
 * 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.
    return of(result as T);
  };
}

以上方法将返回一个安全值。让程序继续工作。

Service 的方法将会窥探 Observable 的数据流,并通过 log() 函数往页面底部发送一条消息。

它们可以使用 RxJS 的 tap 操作符来实现,该操作符会查看 Observable 中的值,使用那些值做一些事情,并且把它们传出来。 这种 tap 回调不会改变这些值本身。

/** GET heroes from the server */
getHeroes (): Observable<Hero[]> {
  return this.http.get<Hero[]>(this.heroesUrl)
    .pipe(
      tap(heroes => this.log('fetched heroes')),
      catchError(this.handleError('getHeroes', []))
    );
}

AsyncPipe 如你所愿,*ngFor 重复渲染出了这些英雄。 仔细看,你会发现 *ngFor 是在一个名叫 heroes$ 的列表上迭代,而不是 heroes。

<li *ngFor="let hero of heroes$ | async" >

$ 是一个命名惯例,用来表明 heroes$ 是一个 Observable,而不是数组。 *ngFor 不能直接使用 Observable。 不过,它后面还有一个管道字符(|),后面紧跟着一个 async,它表示 Angular 的 AsyncPipe。 AsyncPipe 会自动订阅到 Observable,这样你就不用再在组件类中订阅了。

 

posted @ 2018-12-25 20:15  Allen●J  阅读(480)  评论(0编辑  收藏  举报