加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Angular HTTP Client 快速入门

发布时间:2020-12-17 09:06:05 所属栏目:安全 来源:网络整理
导读:之前 激动人心的 Angular HttpClient 这篇文章已经介绍过 HttpClient ,今天看到 angular-university 博客中介绍 HttpClient 的文章,内容很详细,我就简单做了整理。有兴趣的话,建议直接阅读 原文。 HttpClientModule 应用 导入新的 HTTP Module import {H

之前 激动人心的 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"}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读