14 HttpClientModule
该模块用于发送 Http 请求,用于发送请求的方法都返回 Observable 对象。
14.1 QuickStart
- 引入 HttpClientModule 模块
// app.module.ts
import { HttpClientModule } from '@angular/common/http';
imports: [
HttpClientModule, // http
],
- 注入 HttpClient 服务实例对象,用于发送请求
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-quick-start',
templateUrl: './quick-start.component.html',
styleUrls: ['./quick-start.component.css']
})
export class QuickStartComponent {
constructor(private http: HttpClient) { }
}
- 发送请求
src/app/components/http-client/quick-start/quick-start.component.ts
:
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-quick-start',
templateUrl: './quick-start.component.html',
styleUrls: ['./quick-start.component.css']
})
export class QuickStartComponent implements OnInit {
constructor(private http: HttpClient) { }
ngOnInit(): void {
this.http.get('https://jsonplaceholder.typicode.com/users').subscribe(console.log)
}
}
14.2 请求方法
this.http.get(url [, options]);
this.http.post(url, data [, options]) ;
this.http.delpte(url (, options]);
this.http.put(url, data [, options]);
14.3 HttpParams Usage
- HttpParams类
/**
* An HTTP request/response body that represents serialized parameters,
* per the MIME type `application/x-www-form-urlencoded`.
*
* This class is immutable; all mutation operations return a new instance.
*
* @publicApi
*/
export declare class HttpParams {
private map;
private encoder;
private updates;
private cloneFrom;
constructor(options?: HttpParamsOptions);
/**
* Reports whether the body includes one or more values for a given parameter.
* @param param The parameter name.
* @returns True if the parameter has one or more values,
* false if it has no value or is not present.
*/
has(param: string): boolean;
/**
* Retrieves the first value for a parameter.
* @param param The parameter name.
* @returns The first value of the given parameter,
* or `null` if the parameter is not present.
*/
get(param: string): string | null;
/**
* Retrieves all values for a parameter.
* @param param The parameter name.
* @returns All values in a string array,
* or `null` if the parameter not present.
*/
getAll(param: string): string[] | null;
/**
* Retrieves all the parameters for this body.
* @returns The parameter names in a string array.
*/
keys(): string[];
/**
* Appends a new value to existing values for a parameter.
* @param param The parameter name.
* @param value The new value to add.
* @return A new body with the appended value.
*/
append(param: string, value: string | number | boolean): HttpParams;
/**
* Constructs a new body with appended values for the given parameter name.
* @param params parameters and values
* @return A new body with the new value.
*/
appendAll(params: {
[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
}): HttpParams;
/**
* Replaces the value for a parameter.
* @param param The parameter name.
* @param value The new value.
* @return A new body with the new value.
*/
set(param: string, value: string | number | boolean): HttpParams;
/**
* Removes a given value or all values from a parameter.
* @param param The parameter name.
* @param value The value to remove, if provided.
* @return A new body with the given value removed, or with all values
* removed if no value is specified.
*/
delete(param: string, value?: string | number | boolean): HttpParams;
/**
* Serializes the body to an encoded string, where key-value pairs (separated by `=`) are
* separated by `&`s.
*/
toString(): string;
private clone;
private init;
}
- HttpParamsOptions接口
/**
* Options used to construct an `HttpParams` instance.
*
* @publicApi
*/
export declare interface HttpParamsOptions {
/**
* String representation of the HTTP parameters in URL-query-string format.
* Mutually exclusive with `fromObject`.
*/
fromString?: string;
/** Object map of the HTTP parameters. Mutually exclusive with `fromString`. */
fromObject?: {
[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
};
/** Encoding codec used to parse and serialize the parameters. */
encoder?: HttpParameterCodec;
}
- 使用示例
src/app/components/http-client/http-params-usage/http-params-usage.component.ts
:
import { HttpClient, HttpParams } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-http-params-usage',
templateUrl: './http-params-usage.component.html',
styleUrls: ['./http-params-usage.component.css']
})
export class HttpParamsUsageComponent implements OnInit {
constructor(private http: HttpClient) { }
ngOnInit(): void {
let params = new HttpParams({
// fromObject: { name: 'sam', age: '20' }
fromString: 'name=sam&age=20'
});
params = params.append("sex", "female");
this.http.get('https://jsonplaceholder.typicode.com/users', {
params
}).subscribe(console.log)
}
}
14.4 HttpHeaders Usage
请求头字段的创建需要使用HttpHeader类, 在类实例对象下面有各种操作请求头的方法.
/**
* Represents the header configuration options for an HTTP request.
* Instances are immutable. Modifying methods return a cloned
* instance with the change. The original object is never changed.
*
* @publicApi
*/
export declare class HttpHeaders {
/**
* Internal map of lowercase header names to values.
*/
private headers;
/**
* Internal map of lowercased header names to the normalized
* form of the name (the form seen first).
*/
private normalizedNames;
/**
* Complete the lazy initialization of this object (needed before reading).
*/
private lazyInit;
/**
* Queued updates to be materialized the next initialization.
*/
private lazyUpdate;
/** Constructs a new HTTP header object with the given values.*/
constructor(headers?: string | {
[name: string]: string | string[];
});
/**
* Checks for existence of a given header.
*
* @param name The header name to check for existence.
*
* @returns True if the header exists, false otherwise.
*/
has(name: string): boolean;
/**
* Retrieves the first value of a given header.
*
* @param name The header name.
*
* @returns The value string if the header exists, null otherwise
*/
get(name: string): string | null;
/**
* Retrieves the names of the headers.
*
* @returns A list of header names.
*/
keys(): string[];
/**
* Retrieves a list of values for a given header.
*
* @param name The header name from which to retrieve values.
*
* @returns A string of values if the header exists, null otherwise.
*/
getAll(name: string): string[] | null;
/**
* Appends a new value to the existing set of values for a header
* and returns them in a clone of the original instance.
*
* @param name The header name for which to append the values.
* @param value The value to append.
*
* @returns A clone of the HTTP headers object with the value appended to the given header.
*/
append(name: string, value: string | string[]): HttpHeaders;
/**
* Sets or modifies a value for a given header in a clone of the original instance.
* If the header already exists, its value is replaced with the given value
* in the returned object.
*
* @param name The header name.
* @param value The value or values to set or override for the given header.
*
* @returns A clone of the HTTP headers object with the newly set header value.
*/
set(name: string, value: string | string[]): HttpHeaders;
/**
* Deletes values for a given header in a clone of the original instance.
*
* @param name The header name.
* @param value The value or values to delete for the given header.
*
* @returns A clone of the HTTP headers object with the given value deleted.
*/
delete(name: string, value?: string | string[]): HttpHeaders;
private maybeSetNormalizedName;
private init;
private copyFrom;
private clone;
private applyUpdate;
}
src/app/components/http-client/http-headers-usage/http-headers-usage.component.ts
:
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-http-headers-usage',
templateUrl: './http-headers-usage.component.html',
styleUrls: ['./http-headers-usage.component.css']
})
export class HttpHeadersUsageComponent implements OnInit {
constructor(private http: HttpClient) { }
ngOnInit(): void {
let headers = new HttpHeaders({
test: "Hello"
})
this.http.get('https://jsonplaceholder.typicode.com/users', {
headers
}).subscribe(console.log)
}
}
14.5 Response Content
src/app/components/http-client/http-response-content/http-response-content.component.ts
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-http-response-content',
templateUrl: './http-response-content.component.html',
styleUrls: ['./http-response-content.component.css']
})
export class HttpResponseContentComponent implements OnInit {
constructor(private http: HttpClient) { }
ngOnInit(): void {
let headers = new HttpHeaders({
test: "Hello"
})
this.http.get('https://jsonplaceholder.typicode.com/users', {
observe: 'body'
}).subscribe(console.log)
}
}
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-http-response-content',
templateUrl: './http-response-content.component.html',
styleUrls: ['./http-response-content.component.css']
})
export class HttpResponseContentComponent implements OnInit {
constructor(private http: HttpClient) { }
ngOnInit(): void {
let headers = new HttpHeaders({
test: "Hello"
})
this.http.get('https://jsonplaceholder.typicode.com/users', {
// observe: 'body',
observe: 'response',
}).subscribe(console.log)
}
}
14.6 Interceptors
拦截器是 Angular 应用中全局捕获和修改 HTTP 请求和响应的方式。(Token、Error)拦截器将只拦截使用 HttpClientModule 模块发出的请求。
ng g interceptor <name>
14.6.1 Request Interceptor
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(){}
// 拦截方法
intercept(
// unknown 指定请求体(body)的类型
request: HttpRequest<unknown>,
next: HttpHandler
// unknown 指定响应内容(body)的类型
): Observable<HttpEvent<unknown>>{
// 克隆并修改请求头
const req = request.clone({
setHeaders: {
Authorization: "Bearer xxxxxxx"
}
})
// 通过回调函数将修改店的请求头回传给应用
return next.handle(req)
}
}
ng g interceptor components/http-client/http-interceptors/auth
src/app/components/http-client/http-interceptors/auth.interceptor.ts
:
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor() { }
// 拦截方法
intercept(
// unknown 指定请求体(body)的类型
request: HttpRequest<unknown>,
next: HttpHandler
// unknown 指定响应内容(body)的类型
): Observable<HttpEvent<unknown>> {
// 通过回调函数将修改店的请求头回传给应用
return next.handle(request);
}
}
14.6.2 Response Interceptor
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor() {}
// 拦截方法
intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<any> {
return next.handle(request).pipe(
retry(2), // 重试2次
catchError((error: HttpErrorResponse) => throwError(error))
)
}
}
14.6.3 Interceptor inject
import { AuthInterceptor } from "./auth.interceptor"
import { HTTP_INTERCEPTORS } from "@angular/common/http"
@NgModule({
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}],
})
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor() { }
// 拦截方法
intercept(
// unknown 指定请求体(body)的类型
request: HttpRequest<unknown>,
next: HttpHandler
// unknown 指定响应内容(body)的类型
): Observable<HttpEvent<unknown>> {
// 通过回调函数将修改店的请求头回传给应用
let req = request.clone({
setHeaders: {
hello: "world"
}
}
);
return next.handle(req);
}
}
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor() { }
// 拦截方法
intercept(
// unknown 指定请求体(body)的类型
request: HttpRequest<unknown>,
next: HttpHandler
// unknown 指定响应内容(body)的类型
): Observable<HttpEvent<unknown>> {
// 通过回调函数将修改店的请求头回传给应用
let req = request.clone({
method: "post",
setHeaders: {
hello: "world"
}
}
);
return next.handle(req);
}
}
src/app/components/http-client/http-interceptors/auth.interceptor.ts
:
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable, retry } from 'rxjs';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor() { }
// 拦截方法
intercept(
// unknown 指定请求体(body)的类型
request: HttpRequest<unknown>,
next: HttpHandler
// unknown 指定响应内容(body)的类型
): Observable<HttpEvent<unknown>> {
// 通过回调函数将修改店的请求头回传给应用
let req = request.clone({
// method: "post",
setHeaders: {
hello: "world"
}
}
);
return next.handle(req).pipe(retry(2));
}
}
src/app/components/http-client/http-response-content/http-response-content.component.ts
:
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-http-response-content',
templateUrl: './http-response-content.component.html',
styleUrls: ['./http-response-content.component.css']
})
export class HttpResponseContentComponent implements OnInit {
constructor(private http: HttpClient) { }
ngOnInit(): void {
let headers = new HttpHeaders({
test: "Hello"
})
this.http.get('https://0jsonplaceholder.typicode.com/users', { // link change
// observe: 'body',
observe: 'response',
}).subscribe(console.log)
}
}
拦截器是个服务类
14.7 Angular Proxy
- 在项目的根目录下创建 proxy.conf.json 文件并加入如下代码
- /api/*:在应用中发出的以/api 开头的请求走此代理
- target: 服务器端 URL
- secure:如果服务器端 URL的协议是 https,此项需要为 true
-
changeOrigin:如果服务器端不是localhost,此项需要为 true
-
指定 proxy 配置文件(方式一)
package.json
:
{
"name": "angular-study",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
- 指定 proxy 配置文件(方式二)
src/app/components/http-client/http-proxy/http-proxy.component.ts
:
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-http-proxy',
templateUrl: './http-proxy.component.html',
styleUrls: ['./http-proxy.component.css']
})
export class HttpProxyComponent implements OnInit {
constructor(private http: HttpClient) { }
ngOnInit(): void {
let headers = new HttpHeaders({
test: "Hello"
})
this.http.get("http://localhost:3000/token").subscribe(console.log);
}
}
proxy.conf.json
:
{
"/token": {
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
}
}
package.json
:
{
"name": "angular-study",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
ng serve --proxy-config proxy.conf.json
src/app/components/http-client/http-proxy/http-proxy.component.ts
:
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-http-proxy',
templateUrl: './http-proxy.component.html',
styleUrls: ['./http-proxy.component.css']
})
export class HttpProxyComponent implements OnInit {
constructor(private http: HttpClient) { }
ngOnInit(): void {
let headers = new HttpHeaders({
test: "Hello"
})
this.http.get("/token").subscribe(console.log);
}
}