一、HttpClientModule
HttpClientModule
是用来处理http
请求的服务。使用时需要在根模块中引入并注册这个模块。
app.module.ts
import {
HttpClientModule} from "@angular/common/http";
@NgModule({
...
imports: [BrowserModule,RouteModule,HttpClientModule],
...
})
(一)HttpClient
在组件类中需要引入HttpClient
类。HttpClient
类中实现了HTTP
请求方法。还需要为当前组件注册一个HttpClient
类的实例对象。
import {
HttpClient} from "@angular/common/http";
...
constructor(private http: HttpClient) {
}
实例上的方法可以发送各种http
请求,以get
请求为例
this.http.get("https://jsonplaceholder.typicode.com/users").subscribe((res: any) => {
console.log(res);
})
第一个参数是url地址,第二个可选参数是配置对象
get(url: string, options: {
headers?: HttpHeaders | {
[header: string]: string | string[];
};
observe: 'events';
context?: HttpContext;
params?: HttpParams | {
[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
};
reportProgress?: boolean;
responseType: 'blob';
withCredentials?: boolean;
}): Observable<HttpEvent<Blob>>;
(二)HttpParams
HTTP请求体/响应体,用来表示序列化参数,它们的 MIME类型都是 application/x-www-form-urlencoded
。
MIME类型(Multipurpose Internet Mail Extensions Type
)是一种标识文件格式的方式。Web服务器使用MIME类型来确定要发送的文件和内容如何在Web浏览器中处理。
例如,在HTTP响应头中,Content-Type
字段指定了此次请求返回的内容的MIME类型。常见的MIME类型有:
text/plain
:文本文件text/html
:HTML文件image/jpeg
:JPEG图片文件image/png
:PNG图片文件application/pdf
:PDF文件
如果Web服务器不能正确地将MIME类型与所需的文件关联起来,则可能会导致Web浏览器无法正确渲染页面或下载文件。
HttpParams类的定义如下:
export declare class HttpParams {
constructor (options?: HttpParamsOptions);// 实例化HttpParams类的时候可以传递一个配置对象
has (param: string): boolean;// 判断有没有某个参数
get (param: string): string null;
getAll (param: string): string[] | null;
kefs (): string[];
append (param: string, value: string): HttpParams;
set (param: string, value: string): HttpParams;
delete (param: string, value?: strinq): HttpParams;
toString (): string;
}
append
、set
、delete
方法返回的都是新的HttpParams
,HttpParams
类是不可变的,每个修改类的操作都会返回一个新实例。
创建查询参数的时候,可以传递的配置对象的类:
export declare interface HttpParamsOptions {
fromString?: string; // 参数以查询参数的方式传递进来
fromObject?: {
// 请求参数以对象的形式传递
[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
};
encoder?: HttpParameterCodec; // 参数中编码特殊字符的方式
}
查询参数和路径参数是两种常见的URL参数传递方式。
查询参数是附加在URL路径后面的一段信息,通常以问号(?)开头,并且多个查询参数之间使用与符号(&)隔开。例如:https://www.example.com/products?id=123&color=red
路径参数是位于URL路径中的动态部分,其格式通常为冒号(:)加上参数名。例如:https://www.example.com/products/:id,其中:id就是路径参数。
它们的主要区别在于:
- 查询参数不会影响请求被路由到哪个控制器或方法,而路径参数可能会影响。
- 路径参数只能表示一个值,而查询参数可以包含多个值,通过使用相同的名称来定义这些值即可实现。
使用fromObject
和fromString
只有书写方式是不一样的,请求的表现行为都是一样的
let httpParams = new HttpParams({
fromObject: {
name: "zhangsan", age: "18"}});
httpParams = httpParams.set("name", "lisi");
// let httpParams = new HttpParams({fromString: "name=zhangsan&age=18"});
this.http.get("https://jsonplaceholder.typicode.com/users", {
params: httpParams}).subscribe((res: any) => {
console.log(res);
})
(三)HttpHeaders
HttpHeaders
类是一个可以用来操作请求头的类。定义的方式和HttpParams
类似
class HttpHeaders {
constructor(headers?: string | {
[name: string]: string | string[]; })
has(name: string): boolean
get(name: string): string | null
keys(): string[]
getAll(name: string): string[] | null
append(name: string, value: string | string[]): HttpHeaders
set(name: string, value: string | string[]): HttpHeaders
delete(name: string, value?: string | string[]): HttpHeaders
}
向请求头中增加一个字段:
let headers = new HttpHeaders({
test: "test"});
this.http.get("https://jsonplaceholder.typicode.com/users", {
headers}).subscribe((res: any) => {
console.log(res);
})
(四)响应内容
通过Http
请求的oberve
属性控制相应内容。observe
属性的可选值有两种:body
或response
。设置成body
的时候在订阅者中接收到的就是返回的数据;设置成response
的时候在订阅者中接收到的就是完整的响应体。
(五)拦截器
在发送请求和接收响应的途中,使用拦截器可以全局捕获和修改http
请求和响应的方式。拦截器可以拦截由HttpClientModule
发出的所有请求。
1.创建拦截器
创建拦截器需要使用Angular-cli
提供的命令行工具: ng g interceptor auth
。创建一个名字为auth
的拦截器。运行这句代码之后,Angular会在app目录下创建一个auth.intercepter.ts
该文件中有Angular
为我们生成的基础代码。AuthInterceptor
类使用@Injectable()
修饰,是一个服务类,需要实现接口HttpInterceptor
。它作用的范围是整个应用。默认方法intercept()
是起拦截作用的方法,需要接收两个参数,第一个参数是需要拦截的请求实例,第二个参数是next 对象,表示拦截器链表中的下一个拦截器。这个链表中的最后一个 next
对象就是 HttpClient
的后端处理器(backend handler),它会把请求发给服务器,并接收服务器的响应。
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(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
return next.handle(request);
}
}
2.声明拦截器
由于拦截器是一个作用于整个应用的服务类,我们需要在根模块中的providers处,声明拦截器
HTTP_INTERCEPTORS
:一个多重提供者(multi-provider)令牌,它代表所有已注册的HttpInterceptor
构成的数组。
multi
: true
选项。 这个必须的选项会告诉 Angular HTTP_INTERCEPTORS
是一个多重提供者的令牌,表示它会注入一个多值的数组,而不是单一的值。使用这个属性就不需要逐个对拦截器进行注册。
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
},
],
3.修改请求
在拦截器中输出request
请求对象是不可变的,如果想要在拦截器中修改,必须先克隆一份当前的请求实例,然后修改属性后把新的请求实例传递给下一个拦截器。在拦截其中使用请求实例上的clone()
方法就可以实现对请求实例的克隆,clone()
方法接受一个对象作为参数,里面设置的属性就会覆盖原有的属性。要设置请求头,可以使用setHeaders
属性;更改参数使用setParams
属性。
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
let newRequest = request.clone({
setHeaders: {
hello: "angular"
},
setParams: {
name: "wangwu"
}
})
return next.handle(newRequest);
}
4.修改响应
next.handle()
方法返回的是一个Observable
实例,在其后面可以使用pipe()
方法和操作符对返回值进行操作。例如可以使用retry
操作符,当请求失败的时候,会重新尝试传递给retry()
方法的次数
return next.handle(newRequest).pipe(
retry(2)
);
可以在get
请求中将url
写错,在请求时,就会发出三次请求,重试了两次