angular-HttpClient Communicates with Server Get Post Put Delete Http Interceptor Request Explanation

Keywords: JSON Attribute angular Spring

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...

Posted by mohson on Wed, 12 Dec 2018 13:27:06 -0800