【Angular学习】(五)HTTPClient

@angular/common/http 中的 HttpClient 类为 Angular 应用程序提供了一个简化的 API 来实现 HTTP 客户端功能。它基于浏览器提供的 XMLHttpRequest 接口。

使用方法

导入

导入 HttpClientModule 模块

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { HttpClientModule } from "@angular/common/http";

import { AppComponent } from "./app.component";

@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 请求

以下数据都使用https://jsonplaceholder.typicode.com/提供的REST风格API的模拟数据

import { Component, OnInit } from "@angular/core";
import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http";

import { Observable } from "rxjs";
import { tap } from "rxjs/operators";

interface Todo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: "app-root",
  template: `
    <ul *ngIf="todos$ | async as todos else noData">
        <li *ngFor="let todo of todos">
            <span>Title: {{todo.title}}</span> —— 
            <span>Completed: {{todo.completed}}</span>
        </li> 
    </ul>
    <ng-template #noData>No Data Available</ng-template>
`
})
export class AppComponent implements OnInit {
  todos$: Observable<Todo[]>;
  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.todos$ = this.http
      .get<Todo[]>(
        "https://jsonplaceholder.typicode.com/todos?_page=1&_limit=10"
      )
      .pipe(tap(console.log));
  }
}

设置查询参数

假设发送 Get 请求时,需要设置对应的查询参数,预期的 URL 地址如下:

https://jsonplaceholder.typicode.com/todos?_page=1&_limit=10

创建 HttpParams 对象

import { HttpClient, HttpParams } from "@angular/common/http";

const params = new HttpParams().set("_page", "1").set("_limit", "10");

ngOnInit() {
  this.todos$ = this.http
    .get<Todo[]>("https://jsonplaceholder.typicode.com/todos", { params })
    .pipe(tap(console.log));
}

通过链式语法调用 set() 方法,构建 HttpParams 对象。
因为 HttpParams 对象是不可变的,通过 set() 方法可以防止该对象被修改。

每当调用 set() 方法,将会返回包含新值的 HttpParams 对象,因此如果使用下面的方式,将不能正确的设置参数。

const params = new HttpParams();

params.set("_page", "1")
params.set("_limit", "10");

使用 fromString

const params = new HttpParams({fromString: "_page=1&_limit=10"});

使用 fromObject

const params = new HttpParams({ fromObject: { _page: "1", _limit: "10" } });

使用 request API

ngOnInit() {
  this.users$ = this.http
    .request("GET", "https://jsonplaceholder.typicode.com/todos", { params })
    .pipe(tap(console.log));
}

获取完整响应

默认情况下,HttpClient 服务返回的是响应体,有时候我们需要获取响应头的相关信息,这时可以设置请求 options 对象的 observe 属性值为 response 来获取完整的响应对象。

this.http.get("https://jsonplaceholder.typicode.com/todos/1", {
  observe: "response"
})
.subscribe(res => {
   console.dir("Response: " + res.status);
});

设置响应类型

如果期望的响应对象的格式不是 JSON,可以通过 responseType 属性来设定响应类型

this.http.get("https://jsonplaceholder.typicode.com/todos/1", {
  responseType: "text"
}).subscribe(text => {
   console.log("Response: " + text);
});

设置 Http Headers

const params = new HttpParams({ fromObject: { _page: "1", _limit: "10" } });
const headers = new HttpHeaders().set("token", "iloveangular");

ngOnInit() {
  this.todos$ = this.http
    .get<Todo[]>("https://jsonplaceholder.typicode.com/todos", {
        headers,
        params
     })
     .pipe(tap(console.log));
 }

发送 Put 请求

const headers = new HttpHeaders().set(
  "Content-type",
  "application/json; charset=UTF-8"
);

updateFirstTodo() {
    this.http
      .put(
        "https://jsonplaceholder.typicode.com/todos/1",
        {
          userId: 1,
          id: 1,
          title: "delectus aut autem",
          completed: true
        },
        { headers }
      )
      .subscribe(
        val => {
          console.log("Put call successful value returned in body", val);
        },
        error => {
          console.log("Put call in error", error);
        },
        () => {
          console.log("The PUT observable is now completed.");
        }
      );
}

发送 Delete 请求

const headers = new HttpHeaders().set(
  "Content-type",
  "application/json; charset=UTF-8"
);

deleteFirstTodo() {
    this.http
      .delete("https://jsonplaceholder.typicode.com/todos/1", {
        headers
      })
      .subscribe(
        val => {
          console.log("Delete call successful value returned in body", val);
        },
        error => {
          console.log("Delete call in error", error);
        },
        () => {
          console.log("The Delete observable is now completed.");
        }
      );
}

发送 Post 请求

const headers = new HttpHeaders().set(
  "Content-type",
  "application/json; charset=UTF-8"
);

createNewTodo() {
    this.http
      .post(
        "https://jsonplaceholder.typicode.com/todos",
        {
          userId: 1,
          title: "learn ionic 4",
          completed: false
        },
        { headers }
      )
      .subscribe(
        val => {
          console.log("Post call successful value returned in body", val);
        },
        error => {
          console.log("Post call in error", error);
        },
        () => {
          console.log("The Post observable is now completed.");
        }
      );
  }

并行发送多个 Http 请求

parallelRequests() {
    const parallel$ = forkJoin(
      this.http.get("https://jsonplaceholder.typicode.com/users/1"),
      this.http.get("https://jsonplaceholder.typicode.com/todos/1")
    );

    parallel$.subscribe(values => {
      console.log("all values", values);
    });
 }

顺序发送 Http 请求

sequentialRequests() {
    const sequence$ = this.http
      .get<Todo>("https://jsonplaceholder.typicode.com/todos/1")
      .pipe(
        switchMap(todo => {
          todo.title += " - TEST ";
          return this.http.put("https://jsonplaceholder.typicode.com/todos/1", todo);
        })
      );

    sequence$.subscribe(val => {
      console.log("Put call successful value returned in body", val);
    });
}

获取顺序发送 Http 请求的结果

sequentialRequests() {
    const sequence$ = this.http
      .get<Todo>("https://jsonplaceholder.typicode.com/todos/1")
      .pipe(
        switchMap(
          todo => {
            const newTitle = todo.title + " - TEST ";
            const newTodo = { ...todo, title: newTitle };
            return this.http.put(
              "https://jsonplaceholder.typicode.com/todos/1",
              newTodo
            );
          },
          (firstHTTPResult, secondHTTPResult) => [
            firstHTTPResult,
            secondHTTPResult
          ]
        )
      );

    sequence$.subscribe(val => {
      console.log("Put call successful value returned in body", val);
    });
}

请求异常处理

import { of } from "rxjs";
import { catchError } from "rxjs/operators";

throwError() {
    this.http
      .get("https://jsonplaceholder.typicode.com/simulate-error")
      .pipe(
        catchError(error => {
          console.error("Error catched", error);
          return 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, ...}
Value emitted successfully {description: "Error Value Emitted"}
HTTP Observable completed...

Http 拦截器

定义拦截器

auth.interceptor.ts

import { Injectable } from "@angular/core";
import { HttpEvent, HttpRequest, HttpHandler, HttpInterceptor } from "@angular/common/http";

import { Observable } from "rxjs";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const clonedRequest = req.clone({
      headers: req.headers.set("X-CustomAuthHeader", "iloveangular")
    });
    console.log("new headers", clonedRequest.headers.keys());
    return next.handle(clonedRequest);
  }
}

应用拦截器

import { AuthInterceptor } from "./interceptors/auth.interceptor";

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
Http 进度事件
getData() {
   this.http
      .get("https://jsonplaceholder.typicode.com/todos", {
        observe: 'events',
        reportProgress: true
      })
      .subscribe((event: HttpEvent<any>) => {
        switch (event.type) {
          case HttpEventType.Sent:
            console.log("Request sent!");
            break;
          case HttpEventType.ResponseHeader:
            console.log("Response header received!");
            break;
          case HttpEventType.DownloadProgress:
            const kbLoaded = Math.round(event.loaded / 1024);
            console.log(`Download in progress! ${kbLoaded}Kb loaded`);
            break;
          case HttpEventType.Response:
            console.log("Done!", event.body);
        }
      });
}

以上代码成功运行后,在控制台会输出以下信息:

Request sent!
Response header received!
Download in progress! 6Kb loaded
Download in progress! 24Kb loaded
Done!
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值