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 表示的是一个数组,而不是单个的值;

相关文章
相关标签/搜索