The exciting Angular HttpClient article has already introduced HttpClient, as you can see today.
The article about HttpClient in the angular-university blog is very detailed, so I have made a simple arrangement. If you are interested, read it directly.
The original text.
HttpClientModule application imports new HTTP Module
import {HttpClientModule} from '@angular/common/http';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
Note that JSON is now the default data format, and we don't need explicit parsing. That is, we do not need to use the following code:
http.get(url).map(res => res.json()).subscribe(...)
Now we can write as follows:
http.get(url).subscribe(...)
//Send Get Request
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);
}
}
Setting Query Parameters
Assuming that the corresponding query parameters need to be set when sending the Get request, the expected URL address is as follows:
https://angular-http-guide.firebaseio.com/courses.json?orderBy="$key"&limitToFirst=1
Create HttpParams objects
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))
It should be noted that we construct HttpParams objects by calling set() method through chain grammar. This is because the HttpParams object is immutable and can be prevented from being modified by the set() method.
Whenever the set() method is called, the HttpParams object containing the new value will be returned, so the parameters will not be set correctly if the following method is used.
const params = new HttpParams();
params.set('orderBy', '"$key"')
params.set('limitToFirst', "1");
//Use the fromString grammar
const params = new HttpParams({fromString: 'orderBy="$key"&limitToFirst=1'});
//Using 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));
//Setting up 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));
Send a Put request
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.");
}
);
}
Send Patch requests
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.");
});
}
Send Delete requests
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.");
});
}
Send Post Request
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.");
});
}
Avoid duplicate requests
duplicateRequestsExample() {
const httpGet$ = this.http
.get("/courses.json")
.map(data => _.values(data));
httpGet$.subscribe(
(val) => console.log("logging GET value", val)
);
this.courses$ = httpGet$;
}
In the example above, we are creating an HTTP observable object httpGet, and then we subscribe to it directly. Then, we assign the httpGet object to the courses $member variable, and finally subscribe to the object in the template using the async pipeline.
This will result in sending two HTTP requests, in which case the request is obviously duplicated because we only want to query the data from the back end once. To avoid sending redundant requests, we can use the shareReplay operator provided by RxJS:
// 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();
Send multiple requests in parallel
One way to send HTTP requests in parallel is to use the forkjoin operator in RxJs:
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)
}
);
}
Sequential sending of Http requests
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();
}
Get the result of sending Http requests sequentially
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) );
}
Request exception handling
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...")
);
}
When an exception occurs, the output of the console is as follows:
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 interceptor
Define interceptors
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);
}
}
Configuring Interceptors
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
[ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ]
],
bootstrap: [AppComponent]
})
export class AppModule { }
Http progress events
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);
}
}
);
}
After the above example runs, the possible output of the console is as follows:
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, spring cloud open source actual combat project source code: https://gitee.com/xfdm/FCat
QQ group: 549141844
Code continues to update...