之前 激动人心的 Angular HttpClient 这篇文章已经介绍过 HttpClient
,今天看到 angular-university 博客中介绍 HttpClient 的文章,内容很详细,我就简单做了整理。有兴趣的话,建议直接阅读 原文。
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",response => { console.log("PATCH call in error",() => { 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",response => { console.log("DELETE call in error",() => { console.log("The DELETE observable is now completed."); }); }
发送 Post 请求
httpPostExample() { this.http.post("/courses/-KgVwECOnlc-LHb_B0cQ.json",{ "courseListIcon": "...","description": "TEST","iconUrl": "..","url": "new-url" }) .subscribe( (val) => { console.log("POST call successful value returned in body",response => { console.log("POST call in error",() => { 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 ],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"}原文链接:https://www.f2er.com/angularjs/146747.html