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 防御

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息