HttpClientModule 应用
导入新的 HTTP Module
import {HttpClientModule} from '@angular/common/http' ; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule {}
需要注意的是,现在 JSON 是默认的数据格式,我们不需要再进行显式的解析。即我们不需要再使用以下代码:
http.get(url).map(res => res.json()).subscribe(...)
现在我们可以这样写:
http.get(url).subscribe(...)
发送 Get 请求
import {Component, OnInit} from '@angular/core' ; import {Observable} from "rxjs/Observable" ; import {HttpClient} from "@angular/common/http" ; import * as _ from 'lodash' ; interface Course { description: string; courseListIcon:string; iconUrl:string; longDescription:string; url:string; } @Component({ selector: 'app-root' , template: ` <ul *ngIf="courses$ | async as courses else noData"> <li *ngFor="let course of courses"> {{course.description}} </li> </ul> <ng-template #noData>No Data Available</ng-template> `}) export class AppComponent implements OnInit { courses$: Observable <any> ; constructor(private http:HttpClient) {} ngOnInit() { this .courses$ = this .http .get( "https://angular-http-guide.firebaseio.com/courses.json" ) .map(data => _.values(data)) . do (console.log); } }
设置查询参数
假设发送 Get 请求时,需要设置对应的查询参数,预期的 URL 地址如下:
https: // angular-http-guide.firebaseio.com/courses.json?orderBy="$key"&limitToFirst=1创建 HttpParams 对象
import {HttpParams} from "@angular/common/http" ; const params = new HttpParams() .set( 'orderBy', '"$key"' ) .set( 'limitToFirst', "1" ); this .courses$ = this .http .get( "/courses.json" , {params}) . do (console.log) .map(data => _.values(data))
需要注意的是,我们通过链式语法调用 set() 方法,构建 HttpParams 对象。这是因为 HttpParams 对象是不可变的,通过 set() 方法可以防止该对象被修改。
每当调用 set() 方法,将会返回包含新值的 HttpParams 对象,因此如果使用下面的方式,将不能正确的设置参数。
const params = new HttpParams(); params.set( 'orderBy', '"$key"' ) params.set( 'limitToFirst', "1");使用 fromString 语法
const params = new HttpParams({fromString: 'orderBy="$key"&limitToFirst=1'});使用 request() API
const params = new HttpParams({fromString: 'orderBy="$key"&limitToFirst=1' }); this .courses$ = this .http .request( "GET" , "/courses.json" , { responseType: "json" , params }) . do (console.log) .map(data => _.values(data));
设置 HTTP Headers
const headers = new HttpHeaders().set("X-CustomHeader", "custom header value" ); this .courses$ = this .http .get( "/courses.json" , {headers}) . do (console.log) .map(data => _.values(data));
发送 Put 请求
httpPutExample() { const headers = new HttpHeaders().set("Content-Type", "application/json" ); this .http.put("/courses/-KgVwECOnlc-LHb_B0cQ.json" , { "courseListIcon": ".main-page-logo-small-hat.png" , "description": "Angular Tutorial For Beginners TEST" , "iconUrl": ".angular2-for-beginners.jpg" , "longDescription": "..." , "url": "new-value-for-url" }, {headers}) .subscribe( val => { console.log( "PUT call successful value returned in body" , val); }, response => { console.log( "PUT call in error" , response); }, () => { console.log( "The PUT observable is now completed." ); } ); }
发送 Patch 请求
httpPatchExample() { this .http.patch("/courses/-KgVwECOnlc-LHb_B0cQ.json" , { "description": "Angular Tutorial For Beginners PATCH TEST" , }) .subscribe( (val) => { console.log( "PATCH call successful value returned in body" , val); }, response => { console.log( "PATCH call in error" , response); }, () => { console.log( "The PATCH observable is now completed." ); }); }
发送 Delete 请求
httpDeleteExample() { this .http. delete ("/courses/-KgVwECOnlc-LHb_B0cQ.json" ) .subscribe( (val) => { console.log( "DELETE call successful value returned in body" , val); }, response => { console.log( "DELETE call in error" , response); }, () => { console.log( "The DELETE observable is now completed." ); }); }
发送 Post 请求
httpPostExample() { this .http.post("/courses/-KgVwECOnlc-LHb_B0cQ.json" , { "courseListIcon": "..." , "description": "TEST" , "iconUrl": ".." , "longDescription": "..." , "url": "new-url" }) .subscribe( (val) => { console.log( "POST call successful value returned in body" , val); }, response => { console.log( "POST call in error" , response); }, () => { console.log( "The POST observable is now completed." ); }); }
避免重复请求
duplicateRequestsExample() { const httpGet$ = this .http .get( "/courses.json" ) .map(data => _.values(data)); httpGet$.subscribe( (val) => console.log("logging GET value" , val) ); this .courses$ = httpGet$; }
在上面例子中,我们正在创建了一个 HTTP observable 对象 httpGet$ ,接着我们直接订阅该对象。然后,我们把 httpGet$ 对象赋值给 courses$ 成员变量,最后在模板中使用 async 管道订阅该对象。
这将导致发送两个 HTTP 请求,在这种情况下,请求显然是重复的,因为我们只希望从后端查询一次数据。为了避免发送冗余的请求,我们可以使用 RxJS 提供的 shareReplay 操作符:
// put this next to the other RxJs operator imports import 'rxjs/add/operator/shareReplay' ; const httpGet$ = this .http .get( "/courses.json" ) .map(data => _.values(data)) .shareReplay();
并行发送多个请求
并行发送 HTTP 请求的一种方法是使用 RxJs 中的 forkjoin 操作符:
import 'rxjs/add/observable/forkJoin' ; parallelRequests() { const parallel$ = Observable.forkJoin( this .http.get('/courses/-KgVwEBq5wbFnjj7O8Fp.json' ), this .http.get('/courses/-KgVwECOnlc-LHb_B0cQ.json' ) ); parallel$.subscribe( values => { console.log( "all values" , values) } ); }
顺序发送 Http 请求
sequentialRequests() { const sequence$ = this .http.get<Course>('/courses/-KgVwEBq5wbFnjj7O8Fp.json' ) .switchMap(course => { course.description += ' - TEST ' ; return this .http.put('/courses/-KgVwEBq5wbFnjj7O8Fp.json' , course) }); sequence$.subscribe(); }
获取顺序发送 Http 请求的结果
sequentialRequests() { const sequence$ = this .http.get<Course>('/courses/-KgVwEBq5wbFnjj7O8Fp.json' ) .switchMap(course => { course.description += ' - TEST ' ; return this .http.put('/courses/-KgVwEBq5wbFnjj7O8Fp.json' , course) }, (firstHTTPResult, secondHTTPResult) => [firstHTTPResult, secondHTTPResult]); sequence$.subscribe(values => console.log("result observable " , values) ); }
请求异常处理
throwError() { this .http .get( "/api/simulate-error" ) . catch ( error => { // here we can show an error message to the user, // for example via a service console.error("error catched" , error); return Observable.of({description: "Error Value Emitted" }); }) .subscribe( val => console.log('Value emitted successfully' , val), error => { console.error( "This line is never called " ,error); }, () => console.log("HTTP Observable completed..." ) ); }
当发生异常时,控制台的输出结果:
Error catched HttpErrorResponse {headers: HttpHeaders, status: 404, statusText: "Not Found", url: "http://localhost:4200/api/simulate-error", ok: false , … } Value emitted successfully {description: "Error Value Emitted" } HTTP Observable completed...
Http 拦截器
定义拦截器
import {Injectable} from "@angular/core" ; import {HttpEvent, HttpHandler, HttpInterceptor} from "@angular/common/http" ; import {HttpRequest} from "@angular/common/http" ; import {Observable} from "rxjs/Observable" ; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private authService: AuthService) { } intercept(req: HttpRequest <any>, next: HttpHandler): Observable<HttpEvent<any>> { const clonedRequest = req.clone({ headers: req.headers.set( 'X-CustomAuthHeader' , authService.getToken()) }); console.log( "new headers" , clonedRequest.headers.keys()); return next.handle(clonedRequest); } }配置拦截器
@NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [ [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ] ], bootstrap: [AppComponent] }) export class AppModule { }
Http 进度事件
longRequest() { const request = new HttpRequest( "POST", "/api/test-request" , {}, {reportProgress: true }); this .http.request(request) .subscribe( event => { if (event.type === HttpEventType.DownloadProgress) { console.log( "Download progress event" , event); } if (event.type === HttpEventType.UploadProgress) { console.log( "Upload progress event" , event); } if (event.type === HttpEventType.Response) { console.log( "response received..." , event.body); } } ); }
上面示例运行后,控制台的可能的输出结果:
Upload progress event Object {type: 1, loaded: 2, total: 2 } Download progress event Object {type: 3, loaded: 31, total: 31 } Response Received... Object {description: "POST Response"}
转载自:
Angular HTTP Client 快速入门
查看更多关于Angular学习笔记—HttpClient (转载)的详细内容...