AngularX Http服务总结
自己经常用的方式:
1.首先看httpModule
Angular2的http访问经常采用两种方式:
共同点:导入相应的Module
import {Http, RequestOptions, Response} from '@angular/http';
在module文件中配置
import {HttpModule} from '@angular/http';
imports: [ // import Angular's modules
BrowserModule,
BrowserAnimationsModule,
HttpModule,
在service的构造器中进行注入
constructor(private http: Http) {
super();
}
1.1 用promise实现服务层返回
1 // 获取设置
2 public getOptions(): Promise<any> {
3 return this.http
4 .get(this._optionApiUrl)
5 .toPromise()
6 .then((res: Response) => res.json())
7 .catch((error: any) => Observable.throw(error || 'Server error'));
8 }
其中then里面、catch里面可以自己自定义,之后控制层调用服务层
1 /*获取经营单位数据*/
2 public getUnitInfo() {
3 this.parkManageService.getUnitInfo().then(data => {
4 this.units = data.unit;
5 });
6 }
1.2 用Observable实现服务层
1 /*根据查询条件获取数据*/
2 public getParkInfoByParams(jsonObject: any): Observable<any> {
3 return this.http.request(this.getParkInfoByParamUrl, new RequestOptions({ method: 'GET', body: jsonObject }))
4 .map((res: Response) => res.json())
5 .catch((error: any) => Observable.throw(error || 'Server error'));
6 }
控制层调用
1 /*请求后台数据*/
2 public getSuggests(pageNum: number) {
3 this.suggestService.getSuggestInfo(`/Bi/${ConstantValue.CHECKCODE}/querySuggest/${pageNum}/${this.pageSize}`,
4 this.getSearchParams())
5 .subscribe(
6 data => {
7 // console.log(data);
8 ...............
9 },
10 error => console.log('errorMsg:请求建议信息失败...')
11 );
12 }
2.Angular4 推出了一个新的http请求module:HttpClientModule
导入新的 HTTP Module
1 import {HttpClientModule} from '@angular/common/http';
2
3 @NgModule({
4 declarations: [
5 AppComponent
6 ],
7 imports: [
8 BrowserModule,
9 HttpClientModule
10 ],
11 providers: [],
12 bootstrap: [AppComponent]
13 })
14 export class AppModule {}
需要注意的是,现在 JSON 是默认的数据格式,我们不需要再进行显式的解析。即我们不需要再使用以下代码:
http.get(url).map(res => res.json()).subscribe(...)
现在我们可以这样写:
http.get(url).subscribe(...)
发送get请求
1 public saveUser2() {
2 let url = "http://localhost:8080/financial/user/getUsers/2";
3 this.httpClient
4 .get(url)
5 .subscribe(data => {
6 console.log(data)
7 });
8 }
带参数请求(REST方式请求不建议这样使用参数)
1 import {HttpParams} from "@angular/common/http";
2
3 const params = new HttpParams()
4 .set('orderBy', '"$key"')
5 .set('limitToFirst', "1");
6
7 this.courses$ = this.http
8 .get("/courses.json", {params})9 .subscribe(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
})
.subscribe(data => _.values(data));
设置 HTTP Headers
1 const headers = new HttpHeaders().set("X-CustomHeader", "custom header value");
2
3 this.courses$ = this.http
4 .get(
5 "/courses.json",
6 {headers})
7 .subscribe(data => _.values(data));
发送 Put 请求
1 const headers = new HttpHeaders().set("Content-Type", "application/json");
2 this.http.put("/courses/-KgVwECOnlc-LHb_B0cQ.json",
3 {
4 "courseListIcon": ".../main-page-logo-small-hat.png",
5 "description": "Angular Tutorial For Beginners TEST",
6 "iconUrl": ".../angular2-for-beginners.jpg",
7 "longDescription": "...",
8 "url": "new-value-for-url"
9 },
10 {headers})
11 .subscribe(
12 val => {
13 console.log("PUT call successful value returned in body", val);
14 },
15 response => {
16 console.log("PUT call in error", response);
17 },
18 () => {
19 console.log("The PUT observable is now completed.");
20 }
21 );
22 }
发送 Patch 请求
1 httpPatchExample() {
2 this.http.patch("/courses/-KgVwECOnlc-LHb_B0cQ.json",
3 {
4 "description": "Angular Tutorial For Beginners PATCH TEST",
5 })
6 .subscribe(
7 (val) => {
8 console.log("PATCH call successful value returned in body",
9 val);
10 },
11 response => {
12 console.log("PATCH call in error", response);
13 },
14 () => {
15 console.log("The PATCH observable is now completed.");
16 });
17 }
发送 Delete 请求
1 httpDeleteExample() {
2 this.http.delete("/courses/-KgVwECOnlc-LHb_B0cQ.json")
3 .subscribe(
4 (val) => {
5 console.log("DELETE call successful value returned in body", val);
6 },
7 response => {
8 console.log("DELETE call in error", response);
9 },
10 () => {
11 console.log("The DELETE observable is now completed.");
12 });
13 }
发送 Post 请求
1 httpPostExample() {
2 this.http.post("/courses/-KgVwECOnlc-LHb_B0cQ.json",
3 {
4 "courseListIcon": "...",
5 "description": "TEST",
6 "iconUrl": "..",
7 "longDescription": "...",
8 "url": "new-url"
9 })
10 .subscribe(
11 (val) => {
12 console.log("POST call successful value returned in body", val);
13 },
14 response => {
15 console.log("POST call in error", response);
16 },
17 () => {
18 console.log("The POST observable is now completed.");
19 });
20 }
避免重复请求
1 duplicateRequestsExample() {
2 const httpGet$ = this.http
3 .get("/courses.json")
4 .map(data => _.values(data));
5
6 httpGet$.subscribe(
7 (val) => console.log("logging GET value", val)
8 );
9 this.courses$ = httpGet$;
10 }
在上面例子中,我们正在创建了一个 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
操作符:
1 import 'rxjs/add/observable/forkJoin';
2
3 parallelRequests() {
4
5 const parallel$ = Observable.forkJoin(
6 this.http.get('/courses/-KgVwEBq5wbFnjj7O8Fp.json'),
7 this.http.get('/courses/-KgVwECOnlc-LHb_B0cQ.json')
8 );
9
10 parallel$.subscribe(
11 values => {
12 console.log("all values", values)
13 }
14 );
15 }
顺序发送 Http 请求
1 sequentialRequests() {
2 const sequence$ = this.http.get<Course>('/courses/-KgVwEBq5wbFnjj7O8Fp.json')
3 .switchMap(course => {
4 course.description+= ' - TEST ';
5 return this.http.put('/courses/-KgVwEBq5wbFnjj7O8Fp.json', course)
6 });
7
8 sequence$.subscribe();
9 }
获取顺序发送 Http 请求的结果
1 sequentialRequests() {
2 const sequence$ = this.http.get<Course>('/courses/-KgVwEBq5wbFnjj7O8Fp.json')
3 .switchMap(course => {
4 course.description+= ' - TEST ';
5 return this.http.put('/courses/-KgVwEBq5wbFnjj7O8Fp.json', course)
6 },
7 (firstHTTPResult, secondHTTPResult) => [firstHTTPResult, secondHTTPResult]);
8
9 sequence$.subscribe(values => console.log("result observable ", values) );
10 }
请求异常处理
1 throwError() {
2 this.http
3 .get("/api/simulate-error")
4 .catch( error => {
5 // here we can show an error message to the user,
6 // for example via a service
7 console.error("error catched", error);
8
9 return Observable.of({description: "Error Value Emitted"});
10 })
11 .subscribe(
12 val => console.log('Value emitted successfully', val),
13 error => {
14 console.error("This line is never called ",error);
15 },
16 () => console.log("HTTP Observable completed...")
17 );
18 }
当发生异常时,控制台的输出结果:
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 拦截器
定义拦截器
1 import {Injectable} from "@angular/core";
2 import {HttpEvent, HttpHandler, HttpInterceptor} from "@angular/common/http";
3 import {HttpRequest} from "@angular/common/http";
4 import {Observable} from "rxjs/Observable";
5
6 @Injectable()
7 export class AuthInterceptor implements HttpInterceptor {
8
9 constructor(private authService: AuthService) {
10 }
11
12 intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
13 const clonedRequest = req.clone({
14 headers: req.headers.set('X-CustomAuthHeader', authService.getToken())
15 });
16 console.log("new headers", clonedRequest.headers.keys());
17 return next.handle(clonedRequest);
18 }
19 }
配置拦截器
1 @NgModule({
2 declarations: [
3 AppComponent
4 ],
5 imports: [
6 BrowserModule,
7 HttpClientModule
8 ],
9 providers: [
10 [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ]
11 ],
12 bootstrap: [AppComponent]
13 })
14 export class AppModule { }
Http 进度事件
1 longRequest() {
2 const request = new HttpRequest(
3 "POST", "/api/test-request", {},
4 {reportProgress: true});
5
6 this.http.request(request)
7 .subscribe(
8 event => {
9 if (event.type === HttpEventType.DownloadProgress) {
10 console.log("Download progress event", event);
11 }
12 if (event.type === HttpEventType.UploadProgress) {
13 console.log("Upload progress event", event);
14 }
15 if (event.type === HttpEventType.Response) {
16 console.log("response received...", event.body);
17 }
18 }
19 );
20 }
上面示例运行后,控制台的可能的输出结果:
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"}
世事如棋,乾坤莫测,笑尽英雄啊!