Axios默认配置实现:全局与实例配置合并策略
<|begin▁of▁sentence|># 1. 前言
在上一篇文章中,我们实现了`axios`的基础功能,但到目前为止,我们都只是实现了一个很简单的`axios`,一个最最基础的`axios`,我们还有很多功能没有实现,比如:`axios`的默认配置、拦截器、`xsrf`防御、上传下载进度监控等等。那么从本篇文章开始,我们就来一点一点完善这些功能。
我们先从`axios`的默认配置开始,用过`axios`的同学都知道,`axios`提供了一些默认配置,用户可以选择性的设置一些配置,并且这些配置可以分为两类:
- 全局默认配置:`axios.defaults.xxx`
- 实例默认配置:`axios.create({xxx})`
那么,接下来,我们就为我们的`axios`添加上默认配置功能。
# 2. 默认配置
## 2.1 修改类型定义
由于我们要给`axios`添加默认配置,所以我们需要先修改之前定义的类型。
首先,我们创建一个`src/types/config.ts`文件,在该文件中定义配置对象的类型。
```typescript
export interface AxiosRequestConfig {
url?: string;
method?: Method;
data?: any;
params?: any;
headers?: any;
responseType?: XMLHttpRequestResponseType;
timeout?: number;
}
```
然后,为了让`axios`支持默认配置,我们还需要给`axios`接口添加默认配置属性,修改`src/types/index.ts`:
```typescript
import { AxiosRequestConfig } from "./config";
// 新增
export interface Axios {
defaults: AxiosRequestConfig;
request(config: AxiosRequestConfig): AxiosPromise;
get(url: string, config?: AxiosRequestConfig): AxiosPromise;
delete(url: string, config?: AxiosRequestConfig): AxiosPromise;
head(url: string, config?: AxiosRequestConfig): AxiosPromise;
options(url: string, config?: AxiosRequestConfig): AxiosPromise;
post(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise;
put(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise;
patch(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise;
}
```
另外,我们还需要修改`AxiosInstance`接口,因为当我们使用`axios`的时候,不仅可以`axios(config)`,还可以`axios(url, config)`,并且还可以有默认配置,所以修改如下:
```typescript
export interface AxiosInstance extends Axios {
(config: AxiosRequestConfig): AxiosPromise;
(url: string, config?: AxiosRequestConfig): AxiosPromise;
}
```
## 2.2 添加默认配置
默认配置我们可以在`src/defaults.ts`文件中实现:
```typescript
import { AxiosRequestConfig } from "./types";
const defaults: AxiosRequestConfig = {
method: "get",
timeout: 0,
headers: {
common: {
Accept: "application/json, text/plain, */*",
},
},
};
const methodsNoData = ["delete", "get", "head", "options"];
methodsNoData.forEach((method) => {
defaults.headers[method] = {};
});
const methodsWithData = ["post", "put", "patch"];
methodsWithData.forEach((method) => {
defaults.headers[method] = {
"Content-Type": "application/x-www-form-urlencoded",
};
});
export default defaults;
```
我们定义了 `defaults` 常量,它包含了一些默认的配置,我们在下一节就会把这些默认配置设置到 `axios` 上。其中 `method` 默认为 `get`;`timeout` 默认为 `0`;`headers` 默认包含一个 `common` 的对象, common 里包含 `Accept`属性,另外,对于不同的请求方法,`headers` 配置不同:对于没有 `data` 的请求方法,我们不需要设置 `Content-Type`;而对于有 `data` 的请求方法,我们将 `Content-Type` 默认设置为 `application/x-www-form-urlencoded`。
## 2.3 设置默认配置
给`axios`对象添加`defaults`属性,让用户可以通过`axios.defaults.xxx`来获取或者设置默认配置。
修改`src/core/Axios.ts`:
```typescript
import { AxiosRequestConfig, AxiosPromise, AxiosResponse } from "../types";
import { xhr } from "./xhr";
import { buildURL } from "../helpers/url";
import { transformRequest, transformResponse } from "../helpers/data";
import { processHeaders } from "../helpers/headers";
import defaults from "../defaults";
export default class Axios {
defaults: AxiosRequestConfig;
constructor(initConfig: AxiosRequestConfig) {
this.defaults = initConfig;
}
request(config: AxiosRequestConfig): AxiosPromise {
// 合并配置
config = mergeConfig(this.defaults, config);
config.method = config.method.toLowerCase();
// 省略其他代码
}
// 省略其他方法
}
```
我们给`Axios`类添加了`defaults`成员属性,并且让`Axios`的构造函数接受一个`initConfig`参数,作为用户传入的初始配置,然后合并默认配置和初始配置。
另外,在`request`方法中,我们通过`mergeConfig`函数将默认配置`this.defaults`和用户传入的配置`config`做合并。
`mergeConfig`函数我们在`src/core/mergeConfig.ts`中实现:
```typescript
import { AxiosRequestConfig } from "../types";
export default function mergeConfig(
defaultConfig: AxiosRequestConfig,
userConfig?: AxiosRequestConfig
): AxiosRequestConfig {
const config = Object.create(null);
userConfig = userConfig || {};
for (let key in userConfig) {
mergeField(key);
}
for (let key in defaultConfig) {
if (!userConfig[key]) {
mergeField(key);
}
}
function mergeField(key: string): void {
config[key] = userConfig[key] || defaultConfig[key];
}
return config;
}
```
合并的方式并不是简单的把这两个对象合并,而是根据不同的策略进行合并,不过目前我们还没有添加合并策略,所以目前我们只是简单的用用户配置覆盖默认配置,如果用户配置没有传入,那么就用默认配置。
## 2.4 配置初始化
在创建`axios`对象的时候,我们需要传入默认配置,所以修改`src/axios.ts`:
```typescript
import { AxiosInstance, AxiosRequestConfig } from "./types";
import Axios from "./core/Axios";
import defaults from "./defaults";
import { extend } from "./helpers/util";
function createInstance(config: AxiosRequestConfig): AxiosInstance {
const context = new Axios(config);
const instance = Axios.prototype.request.bind(context);
extend(instance, context);
return instance as AxiosInstance;
}
const axios = createInstance(defaults);
export default axios;
```
在`index.ts`入口文件中,我们引入`./defaults`默认配置,然后调用`createInstance`函数创建`axios`对象的时候把默认配置传进去,这样就能实现默认配置了。
OK,默认配置添加好了,我们接下来在`demo`中测试下效果。
# 3. demo 编写
在 `examples` 目录下创建 `defaults` 目录,在 `defaults` 目录下创建 `index.`:
```
< lang="en">
Defaults example
>
```
再创建 `app.ts` 作为入口文件:
```typescript
import axios from "../../src/index";
axios({
url: "/api/axios",
method: "post",
data: {
msg: "hi",
},
});
axios({
url: "/api/axios",
method: "post",
data: {
msg: "hi",
},
headers: {
"Content-Type": "text/plain;charset=utf-8",
},
});
```
接着在 `server/server.js` 添加新的接口路由:
```javascript
// 添加默认配置接口
router.post("/api/axios", function(req, res) {
res.json({
msg: "hello world",
});
});
```
最后在根目录下的`index.`中加上启动该`demo`的入口:
```
defaults
```
OK,我们在命令行中执行:
```bash
# 同时开启客户端和服务端
npm run server | npm start
```
接着我们打开 `chrome` 浏览器,访问 即可访问我们的 `demo` 了,我们点击 `defaults`,通过`F12`的 `network` 部分我们可以看到发送了两个请求,并且这两个请求都配置了默认的请求头,第一个请求我们没配置`headers`,所以使用了默认的`Content-Type:application/x-www-form-urlencoded`;第二个请求我们配置了`headers`,所以使用了我们配置的`Content-Type:text/plain;charset=utf-8`。


OK,默认配置功能已经实现了!
最新文章
- 智能驾驶与固态电池革新:未来汽车三大技术趋势解析
- 汽车刹车系统解析:从刹车盘到制动总泵的关键知识
- 智能驾驶技术加速演进:激光雷达与V2X引领汽车产业变革
- 汽车底盘技术专属配件解析
- 2023汽车产业三大变革:固态电池突破、自动驾驶升级、车联网生态崛起
- 磷酸铁锂电池:新能源汽车安全与经济性的双重突破
- V2X通信与车载传感器如何重塑智能驾驶体验
- 发动机过热:危险信号与应急处理全指南
- 固态电池与激光雷达引领智能座舱革命
- 新手必看:掌握发动机转速、安全车距与雾灯使用的驾驶技巧
- V2X+高压快充+智能网联:三大技术重塑未来出行
- 电子控制单元优化汽车性能提升驾驶体验
- 汽车天窗排水系统维护指南:导水槽与密封胶条保养要点
- 行驶证如何影响车险保额?核定载人数等关键因素解析
- 防抱死制动系统提升汽车安全性能
- 智能座舱与电动化引领未来车联网新趋势
- 汽车变速箱技术进化史:从手动到智能的全面解析
- 安全驾驶指南:轮胎气压、刹车系统与变速箱保养要点
- 发动机轰鸣汽车飞驰在高速公路上
- 车联网与动力电池革新:自动驾驶时代的汽车技术变革
