Axios配置增强:支持params与auth参数
<|begin▁of▁sentence|># 1. 前言
在上一篇文章中,我们实现了`axios`的请求和响应配置化,即用户可以配置`config`对象中的`headers`、`data`、`timeout`等属性来改变请求和响应。但是,在之前的实现中,我们允许修改的配置属性还是不够多,所以这篇文章中,我们就来丰富`config`对象中的配置属性。
# 2. 需求分析
根据官方`axios`文档,`axios`支持的配置属性除了之前实现的`url`、`method`、`data`、`headers`、`timeout`、`responseType`之外,还有很多,例如:
- `params`:`url`参数,用于`get`请求
- `paramsSerializer`:用于序列化`params`
- `auth`:`HTTP`基础验证
- 等等
由于属性太多,我们不可能在这一篇文章中全部实现,所以我们就挑选几个比较常用的来实现,例如:`params`、`auth`等,其余不常用的等后续用到的时候再实现。
# 3. 代码实现
## 3.1 修改类型定义
由于我们要给`config`对象增加新的属性,所以我们需要先修改之前定义的类型。
我们在`src/types/index.ts`中的`AxiosRequestConfig`中添加如下属性:
```typescript
export interface AxiosRequestConfig {
// 新增
params?: any;
auth?: AxiosBasicCredentials;
// 已有
url?: string;
method?: Method;
data?: any;
headers?: any;
responseType?: XMLHttpRequestResponseType;
timeout?: number;
}
```
其中,`params`属性我们定义为`any`类型,因为它可以是任意类型,例如字符串、对象等。
另外,我们给`auth`属性定义了`AxiosBasicCredentials`类型,该类型我们定义如下:
```typescript
export interface AxiosBasicCredentials {
username: string;
password: string;
}
```
## 3.2 处理 params 参数
我们之前处理`get`请求参数的时候,是将其放在`data`中,然后拼接到`url`上,但是官方`axios`是放在`params`属性中,所以我们也要做同样的处理。
我们在`src/core/xhr.ts`中的`processConfig`函数中,添加对`params`的处理:
```typescript
// src/core/xhr.ts
function processConfig(config: AxiosRequestConfig): void {
config.url = transformUrl(config);
config.headers = transformHeaders(config);
config.data = transformRequestData(config);
}
function transformUrl(config: AxiosRequestConfig): string {
const { url, params } = config;
return buildURL(url, params);
}
```
这里,我们先从`config`中取出`url`和`params`,然后调用`buildURL`函数将`params`参数拼接到`url`上。
## 3.3 处理 auth 参数
`auth`参数是`HTTP`基础验证,它包含两个属性:`username`和`password`。我们在发送请求的时候,需要将这两个属性按照`HTTP`基础验证的规范,将其拼接成一个字符串,然后放到`headers`的`Authorization`属性中。
我们在`src/core/xhr.ts`中的`processHeaders`函数中,添加对`auth`的处理:
```typescript
// src/core/xhr.ts
import { isObject, deepMerge } from "../helpers/util";
import { AxiosRequestConfig } from "../types";
import { isPlainObject } from "../helpers/util";
function processHeaders(config: AxiosRequestConfig): void {
const { headers = {}, data, auth } = config;
// 处理auth
if (auth) {
headers["Authorization"] = "Basic " + btoa(auth.username + ":" + auth.password);
}
// 处理Content-Type
if (isObject(data)) {
if (headers && !headers["Content-Type"]) {
headers["Content-Type"] = "application/json;charset=utf-8";
}
}
return headers;
}
```
这里,我们先从`config`中取出`headers`、`data`和`auth`,然后判断`auth`是否存在,如果存在,就将其按照`HTTP`基础验证的规范,将其拼接成一个字符串,然后放到`headers`的`Authorization`属性中。
## 3.4 修改 buildURL 函数
我们之前实现的`buildURL`函数只能处理`params`为对象的情况,但是官方`axios`的`params`还可以是`URLSearchParams`、`Array`等类型,所以我们也要做相应的处理。
我们在`src/helpers/url.ts`中的`buildURL`函数中,添加对`params`为`URLSearchParams`、`Array`等类型的处理:
```typescript
// src/helpers/url.ts
import { isDate, isObject, isURLSearchParams } from "./util";
export function buildURL(
url: string,
params?: any,
paramsSerializer?: (params: any) => string
): string {
if (!params) {
return url;
}
let serializedParams;
if (paramsSerializer) {
serializedParams = paramsSerializer(params);
} else if (isURLSearchParams(params)) {
serializedParams = params.toString();
} else {
const parts: string[] = [];
Object.keys(params).forEach((key) => {
const val = params[key];
if (val === null || typeof val === "undefined") {
return;
}
let values = [];
if (Array.isArray(val)) {
values = val;
key += "[]";
} else {
values = [val];
}
values.forEach((val) => {
if (isDate(val)) {
val = val.toISOString();
} else if (isObject(val)) {
val = JSON.stringify(val);
}
parts.push(`${encode(key)}=${encode(val)}`);
});
});
serializedParams = parts.join("&");
}
if (serializedParams) {
const markIndex = url.indexOf("#");
if (markIndex !== -1) {
url = url.slice(0, markIndex);
}
url += (url.indexOf("?") === -1 ? "?" : "&") + serializedParams;
}
return url;
}
```
这里,我们首先判断`params`是否存在,如果不存在,直接返回`url`。
然后,我们判断`paramsSerializer`是否存在,如果存在,就调用`paramsSerializer`函数对`params`进行序列化。
如果`paramsSerializer`不存在,但是`params`是`URLSearchParams`类型,我们就调用`params.toString()`方法将其转换成字符串。
如果`paramsSerializer`不存在,且`params`不是`URLSearchParams`类型,我们就按照之前的处理方式,将其转换成字符串。
最后,我们将序列化后的`params`拼接到`url`上。
另外,我们还需要在`src/helpers/util.ts`中添加`isURLSearchParams`函数:
```typescript
// src/helpers/util.ts
export function isURLSearchParams(val: any): val is URLSearchParams {
return typeof val !== "undefined" && val instanceof URLSearchParams;
}
```
## 3.5 修改 transformHeaders 函数
我们之前实现的`transformHeaders`函数只能处理`headers`为对象的情况,但是官方`axios`的`headers`还可以是`Headers`、`Array`等类型,所以我们也要做相应的处理。
我们在`src/helpers/headers.ts`中的`transformHeaders`函数中,添加对`headers`为`Headers`、`Array`等类型的处理:
```typescript
// src/helpers/headers.ts
import { isPlainObject, deepMerge } from "./util";
export function transformHeaders(
headers: any,
data: any
): any {
if (isPlainObject(data)) {
if (headers && !headers["Content-Type"]) {
headers["Content-Type"] = "application/json;charset=utf-8";
}
}
return headers;
}
```
这里,我们只处理了`headers`为对象的情况,因为`headers`为`Headers`、`Array`等类型的情况比较少见,所以我们暂时不做处理。
# 4. 测试
## 4.1 测试 params 参数
我们可以在`examples/base-app.ts`中,添加如下代码:
```typescript
// examples/base-app.ts
axios({
method: "get",
url: "/api/base/get",
params: {
a: 1,
b: 2,
},
});
```
然后,我们可以在浏览器中查看请求的`url`,可以看到`params`参数已经被拼接到`url`上了。

## 4.2 测试 auth 参数
我们可以在`examples/base-app.ts`中,添加如下代码:
```typescript
// examples/base-app.ts
axios({
method: "get",
url: "/api/base/get",
auth: {
username: "admin",
password: "123456",
},
});
```
然后,我们可以在浏览器中查看请求的`headers`,可以看到`Authorization`属性已经被设置成了`Basic YWRtaW46MTIzNDU2`,其中`YWRtaW46MTIzNDU2`是`admin:123456`的`base64`编码。

# 5. 总结
在本篇文章中,我们给`config`对象增加了`params`和`auth`两个属性,并且对`buildURL`函数和`processHeaders`函数做了相应的修改,使其能够处理`params`和`auth`参数。
另外,我们还对`buildURL`函数做了增强,使其能够处理`params`为`URLSearchParams`、`Array`等类型的情况。
在下一篇文章中,我们将实现`axios`的拦截器功能。
最新文章
- 激光雷达:自动驾驶的3D慧眼与安全革命
- 机动车维修发票规范指南:从开具到维权的全流程解析
- 燃油车百年发展史:从机械革命到新能源转型
- 汽车蓄电池极板硫化:原因、危害及预防处理全解析
- 电动化浪潮下:电池技术、电机系统与充电基建的突破与未来
- 方向盘“失联”之后:线控转向如何重塑驾驶与安全
- 宝马X5越野性能卓越适合各种地形
- 智能网联与新能源革命:未来出行的三大技术变革
- 从“坐船”到“贴地飞行”:悬架优化全攻略
- 风扇转动汽车引擎散热降温
- 雨天行车安全指南:排气管涉水、雨刮器检查与轮胎气压维护
- 汽车防盗报警器实时监控安全防护
- 车辆油耗增加导致经济损失严重
- 五点式安全带:全方位保护与未来智能安全技术解析
- 智能汽车如何'看见'世界:激光雷达与多传感器融合技术解析
- 电动化与智能化双轮驱动:固态电池、激光雷达、智能座舱重塑汽车未来
- L3自动驾驶核心技术解析:从传感器融合到安全冗余
- 汽车传动系统优化技术
- 汽车变速箱技术全解析:从进化历程到未来趋势
- 长城脚下汽车驰骋
