angular2-HttpClient

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

 

安裝本模塊

 

import {HttpClientModule} from '@angular/common/http';  
imports: [ BrowserModule, // Include it under 'imports' in your application module // after BrowserModule. HttpClientModule, ],

 

{
  "results": [
    "Item 1",
    "Item 2",
  ]
}
//HttpClient的get()方法可讓訪問此數據的代碼很是直白: this.http.get('/api/items').subscribe(data => { // Read the result field from the JSON response. this.results = data['results']; (寫成,TypeScript 就會抱怨說來自HTTP的沒有一個名叫的屬性) }); data.resultsObjectresults

  

響應體的類型檢查

上面的例子中,訪問data['results']是用方括號語法來取得results字段的。若是寫成data.results,TypeScript 就會抱怨說來自HTTP的Object沒有一個名叫results的屬性。 那是由於HttpClient把 JSON 格式的響應體解析成了一個Object,它並不知道這個對象的形態應該是什麼。java

 

其實能夠告訴HttpClient這個響應體應該是什麼類型的,並且這是推薦的作法。 要這樣作,首先咱們要定義一個接口來描述這個類型的正確形態:json

 

interface ItemsResponse {
  results: string[];
}

http.get<ItemsResponse>('/api/items').subscribe(data => {
  // data is now an instance of type ItemsResponse, so you can do this:
  this.results = data.results;
});

  

讀取完整的響應體

經過observe選項來告訴HttpClient,你想要完整的響應信息,而不是隻有響應體:後端

http
  .get<MyJsonData>('/data.json', {observe: 'response'})
  .subscribe(resp => {
    console.log(resp.headers.get('X-Custom-Header'))
    console.log(resp.body.someField);
  });

  

錯誤處理

http
  .get<ItemsResponse>('/api/items')
  .subscribe(
    // Successful responses call the first callback.
    data => {...},
    // Errors will call this callback instead:
    err => {
      console.log('Something went wrong!');
    }
  );

  

.retry() 操做符

這種策略對於那些臨時性的並且不大可能重複發生的錯誤會頗有用api

http
  .get<ItemsResponse>('/api/items')
  // Retry this request up to 3 times.
  .retry(3)
  // Any errors after the 3rd retry will fall through to the app.
  .subscribe(...);

  

請求非 JSON 數據

 

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

  

把數據發送到服務器

發起一個 POST 請求

const body = {name: 'Brad'};
http.post('/api/developers/add', body).subscribe(...);

  

注意這個subscribe()方法。 全部從HttpClient返回的可觀察對象都是冷的(cold),也就是說,它們只是發起請求的藍圖而已。在咱們調用subscribe()以前,什麼都不會發生,而當咱們每次調用subscribe()時,就會獨立發起一次請求。 好比,下列代碼會使用一樣的數據發送兩次一樣的 POST 請求:數組

const req = http.post('/api/items/add', body);
// 0 requests made - .subscribe() not called.
req.subscribe();
// 1 request made.
req.subscribe();
// 2 requests made

  

 

配置請求中的其它部分

除了 URL 和可能的請求體以外,要發送的請求中你可能還但願配置一些別的東西。全部這些均可以經過給此次請求傳一個額外的options(選項)對象來解決瀏覽器

http
  .post('/api/items/add', body, {
    headers: new HttpHeaders().set('Authorization', 'my-auth-token'),
  })
  .subscribe();

HttpHeaders類是不可變對象(immutable),因此每一個set()都會返回一個新實例,而且應用上這些修改緩存

 

URL 參數

 

http
  .post('/api/items/add', body, {
    params: new HttpParams().set('id', '3'),
  })
  .subscribe();

這種狀況下,咱們會往 URL /api/items/add?id=3 上發送一個 POST 請求服務器

 

攔截全部的請求和響應。

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

寫一個攔截器

要實現一個攔截器,就要聲明一個實現了HttpInterceptor接口的類,它只有一個intercept()方法。下面是一個最簡單的攔截器,它什麼也不作,只是簡單的轉發請求而不作任何修改:

 

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

@Injectable()
export class NoopInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req);
  }
}

  

intercept是一個方法,它把一個請求對象轉換成一個返回這個響應的可觀察對象(Observable)

固然,大多數時候,攔截器會對請求作一些小的修改,而後才把它轉給攔截器鏈中的其它部分,也就是所傳進來的next參數。next是一個HttpHandler,是一個相似於intercept的接口,它會把一個請求對象轉換成一個可觀察的響應對象。在攔截器中,next老是表明位於攔截器鏈中的下一個攔截器(若是有的話),若是沒有更多攔截器了,它就會是最終的後端。因此,大多數攔截器的最後一句都會以它們轉換後請求對象爲參數調用next.handle函數。

 

像上面這樣簡單地聲明NoopInterceptor並不會讓咱們的應用實際使用它。還要經過把它做爲攔截器提供給咱們的應用模塊纔會生效,代碼以下:

 

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

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

  

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

 

順序

當咱們在一個應用中提供了多個攔截器時,Angular 會按照你提供時的順序應用它們(譯註:即模塊的providers數組中列出的順序)。

不可變性

攔截器要檢查和修改準備發出的請求和接收進來的響應。可是,你可能會驚奇的發現HttpRequestHttpResponse類在很大程度上倒是不可變的。

由於應用可能會重發請求,而攔截器鏈可能會屢次處理同一個請求。若是請求是可變的,每次重試時的請求均可能和原始的請求不同。而不可變對象能夠確保攔截器每次重試時處理的都是同一個請求。

 

若是確實須要修改請求體,咱們就得本身複製它,修改這個複本,而後使用clone()來複制這個請求,並使用這個新的請求體。

因爲請求都是不可變的,因此不能直接修改它們。要想修改,就使用clone()函數:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  // This is a duplicate. It is exactly the same as the original.
  const dupReq = req.clone();
  const secureReq = req.clone({url: req.url.replace('http://', 'https://')});
}

  

設置新的頭

攔截器的常見用途之一是爲所發出的請求設置默認的請求頭。好比,假設咱們有一個可注入的AuthService,它能夠提供一個認證令牌,而咱們但願寫一個攔截器,它負責把這個令牌添加到全部要發出的請求中:

 

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
 
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) {}
 
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authHeader = this.auth.getAuthorizationHeader();
    const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)});
   //簡寫: const authReq = req.clone({setHeaders: {Authorization: authHeader}});
return next.handle(authReq); } }

這種能夠修改頭的攔截器能夠用於不少不一樣的操做,好比:

    • 認證 / 受權

    • 控制緩存行爲。好比If-Modified-Since

    • XSRF 防禦

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息