Angular 4+ HttpClient

我的博客遷移至 http://www.sulishibaobei.com  處;css

這篇,算是上一篇Angular 4+ Http的後續html

Angular 4.3.0-rc.0 版本已經發布🐦。在這個版本中,咱們等到了一個使人興奮的新功能 - HTTPClient API 的改進版本;前端

HttpClient 是已有 Angular HTTP API 的演進,它在一個單獨的 @angular/common/http 包中。這是爲了確保現有的代碼庫能夠緩慢遷移到新的 API;git

大多數前端應用都須要經過 HTTP 協議與後端服務器通信。現代瀏覽器支持使用兩種不一樣的 API 發起 HTTP 請求:XMLHttpRequest 接口和 fetch() API;github

@angular/common/http中的HttpClient類,Angular 爲應用程序提供了一個簡化的 API 來實現 HTTP 功能。它基於瀏覽器提供的XMLHttpRequest接口。 HttpClient帶來的其它優勢包括:可測試性、強類型的請求和響應對象、發起請求與接收響應時的攔截器支持,以及更好的、基於可觀察(Observable)對象的錯誤處理機制;typescript

1.如何使用httpClient;json

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {HttpClientModule} from '@angular/common/http';
@NgModule({
  imports: [
    BrowserModule,
    // Include it under 'imports' in your application module
    // after BrowserModule.
    HttpClientModule,
  ],
})
export class MyAppModule {}

注意:導入方式和HttpModule同樣的,記得要在BrowserModule後面導入;區別是:在@angular/common/http 模塊裏面,而不是@angular/http中後端

這樣咱們可使用這些啦:api

class HttpClient {
  request(first: string|HttpRequest<any>, url?: string, options: {...}): Observable<any>
  delete(url: string, options: {...}): Observable<any>
  get(url: string, options: {...}): Observable<any>
  head(url: string, options: {...}): Observable<any>
  jsonp<T>(url: string, callbackParam: string): Observable<T>
  options(url: string, options: {...}): Observable<any>
  patch(url: string, body: any|null, options: {...}): Observable<any>
  post(url: string, body: any|null, options: {...}): Observable<any>
  put(url: string, body: any|null, options: {...}): Observable<any>
}   

2.發起一個請求來獲取Json數據;數組

   首先建立一個json文件,其實就是上一篇的同一個json文件:

{
  "data": [
    { "id": 1, "name": "Windstorm" },
    { "id": 2, "name": "Bombasto" },
    { "id": 3, "name": "Magneta" },
    { "id": 4, "name": "Tornado" }
  ]
}

怎麼調用Http請求呢?

   2.1 app.componment.ts;

import { Component,OnInit } from '@angular/core';
import {HttpClient} from '@angular/common/http';  /*註釋1*/
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent  implements OnInit {
constructor(private http:HttpClient){} 
 datas:string[];
  ngOnInit(){
    this.http.get('./assets/heroes.json').subscribe(data=>{  /*註釋2*/
         this.datas=data['data'];
         console.log(this.datas)
    }) 
  }
}

注意:

  註釋1: 組件中引入的是HttpClient,也是在單獨的庫,@angular/common/http中;

               以前的項目裏面引入的一直都是http,這就是改版後的區別;

  註釋2:如今 JSON 是默認的數據格式,咱們不須要再進行顯式的解析;this.http.get('xx').subscribe();

              以前的還須要res.json()去手動轉;

 還有一點要注意:我並無去hero.service.ts裏面去操做了,而是直接在組件中發請求獲取數據,這樣更加簡單明瞭;

<div>
  <ul  *ngFor="let data of datas">
    <li>{{data.id}}  {{data.name}}</li>
  </ul>
</div>

html代碼仍是同樣簡單,並無改變;

這是相比較以前的Http簡單的方式;

  get(url: string, options: {
    headers?: HttpHeaders,
    observe?: HttpObserve,
    params?: HttpParams,
    reportProgress?: boolean,
    responseType?: 'arraybuffer'|'blob'|'json'|'text',
    withCredentials?: boolean,
  }): Observable<any> 

這是get方法詳解,請注意,返回的都是observable對象,而不是使用promise了;

3.響應體的檢查

   3.1上面的代碼中:

 datas:string[];   //定義一個接口來描述這個類型的正確形態

this.datas=data['data']; /*註釋1*/

 註釋1:

   咱們取json對象data值時要data['data'],而不是以前的data.data了;若是改爲:

 this.datas=data.data;

會報錯:

 does not exist on type 'Object

那是由於HttpClient把 JSON 格式的響應體解析成了一個Object,它並不知道這個對象的形態應該是什麼。因此咱們應該告訴你須要取得data是個什麼類型;這也是更符合typescript語法的作法;

4. 若是將要獲取的不是JSON文件如何?

 this.http.get('/assets/1.txt',{responseType:'text'}).subscribe(
      data=>console.log(data)
)

注意:這樣咱們就要指定須要獲取的文本格式;

  控制檯將會打印個人1.txt中的內容:www.sulishibaobei.com

 5.如何帶參查詢數據

  const params = new HttpParams()
    .set('id', '1').set('name','Windstorm')
    this.cus=this.http.get('assets/heroes.json',{params})
    .do(console.log)
    .map(data=>
        console.log( _.values(data))
);

引入:httpParams參數:

import {HttpClient, HttpParams} from '@angular/common/http';

咱們經過鏈式語法調用set()方法,構建了params對象;每當set()方法被調用時,都會包含新的值進來,而且防止以前對象不被修改;

http://localhost:4200/assets/heroes.json?id=1&name=Windstorm

請求的連接地址將會是這樣的形式;這個有點像http裏添加url參數;

還能夠設置Headers;

const headers = new HttpHeaders().set("X-CustomHeader", "custom header value");

還有其餘的請求,以後會逐一分析;

另外還有幾點比較重要的:

  多行併發發送請求和順序發送請求,避免發送重複請求;

避免發送重複請求

import 'rxjs/add/operator/shareReplay';

const httpGet = this.http
    .get("assets/heroes.json")
    .map(data => _.values(data))
    .shareReplay();

這樣即便你將 httpGet再賦值給另外一個變量,或重複調用也不會再次請求了
並行發送 HTTP 請求的一種方法是使用 RxJs 中的 forkjoin 操做符:

import 'rxjs/add/observable/forkJoin';
Requests() {
    const result = Observable.forkJoin(
        this.http.get('/assets/heroes.json'),
        this.http.get('/assets/heroes.json')
    );

   result.subscribe(
        values => {
            console.log("all values", values)
        }
    );
}
順序發送請求
sequentialRequests() {
    const sequence$ = this.http.get<Hero>('/assets/heroes.json')
        .switchMap(hero => {
            hero.id+= ' - TEST ';
            return this.http.put('/assets/heroes.json', hero)
        });
        
    sequence$.subscribe();
}

6. 攔截器  (攔截全部的請求和響應這也是@angular/common/http的核心特性之一)

    它能聲明一些攔截器,攔在應用和後端之間。當應用程序發起一個請求時,攔截器能夠在請求被髮往服務器以前先轉換這個請求。而且在應用看到服務器發回來的響應以前,轉換這個響應。這對於處理包括認證和記錄日誌在內的一系列工做都很是有用。

  6.1 如何寫一個攔截器

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable} from 'Rxjs/Observable';

@Injectable()
export class NoopInterceptor implements HttpInterceptor {
   intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
       return next.handle(req).map(event => {
        if (event instanceof HttpResponse) {
          if (event.status === 401) {
            // JWT expired, go to login
          }
        }
        return event;
      }
   } 
}

1.intercept是一個方法,它把一個請求對象轉換成一個返回這個響應的可觀察對象(Observable)。從這個意義上說,每一個攔截器都要徹底本身處理這個請求;

2.響應攔截器能夠經過在 next.handle(req) 返回的流對象 (即 Observable 對象) 上應用附加的 Rx 操做符來轉換響應事件流對象;

內部能夠作本身的處理操做;

可是此時攔截器還未使用在組件上;

 

import {NgModule} from '@angular/core';
import {HTTP_INTERCEPTORS} from '@angular/common/http';

@NgModule({
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: NoopInterceptor,
    multi: true,
  }],
})
export class AppModule {}

 

providers裏面配置咱們的信息;

注意multi: true選項。這是必須的,由於它會告訴 Angular 這個 HTTP_INTERCEPTORS 表示的是一個數組,而不是單個的值;

相關文章
相關標籤/搜索