# Axios请求配置
https://www.axios-http.cn/docs/req_config
# Axios拦截器
http://www.axios-js.com/zh-cn/docs/#%E6%8B%A6%E6%88%AA%E5%99%A8
在请求或响应被 then 或 catch 处理前拦截它们。
拦截器分为请求和响应两种,对应request和respones
添加规则:use
删除规则:eject
import axios from 'axios';
// 创建一个 Axios 实例
const instance = axios.create({
baseURL: 'https://api.example.com',
});
// 请求拦截器
instance.interceptors.request.use(
(config) => {
// 在请求发送之前做一些处理,例如添加请求头等
console.log('Request Interceptor:', config);
return config;
},
(error) => {
// 处理请求错误
console.error('Request Error Interceptor:', error);
return Promise.reject(error);
}
);
// 响应拦截器
instance.interceptors.response.use(
(response) => {
// 在响应数据被处理之前做一些处理
console.log('Response Interceptor:', response);
return response;
},
(error) => {
// 处理响应错误
console.error('Response Error Interceptor:', error);
return Promise.reject(error);
}
);
export default instance;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 请求参数类型
post(url: string, data?: any, config?: AxiosRequestConfig)
request.body的几种常见格式
application/x-www-form-urlencoded:
这是表单提交的默认格式,不支持文件类型.它的请求格式是以&符号连接的键值对.(查询字符串)
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
key1=val1&key2=val2
2
3
4
multipart/form-data:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryPAlLG7hJKNYc4ft3
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
demo
------WebKitFormBoundaryPAlLG7hJKNYc4ft3
Content-Disposition: form-data; name="file"; filename="demo.png"
Content-Type: image/png
------WebKitFormBoundaryPAlLG7hJKNYc4ft3--
2
3
4
5
6
7
8
9
10
11
12
13
application/json:
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"name":"xfly","age": 24, "hobby":["x","xx","xxx"]}
2
3
4
5
# Axios解读:
axios源码解读:https://juejin.cn/post/6844903898172358669
node环境下打印axios
const axios = require('axios');
console.log(axios);
2
<ref *1> [Function: wrap] {
request: [Function: wrap],
getUri: [Function: wrap],
delete: [Function: wrap],
get: [Function: wrap],
head: [Function: wrap],
options: [Function: wrap],
post: [Function: wrap],
put: [Function: wrap],
patch: [Function: wrap],
defaults: {
adapter: [Function: httpAdapter],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus],
headers: {
common: [Object],
delete: {},
get: {},
head: {},
post: [Object],
put: [Object],
patch: [Object]
}
},
interceptors: {
request: InterceptorManager { handlers: [] },
response: InterceptorManager { handlers: [] }
},
Axios: [Function: Axios],
create: [Function: create],
Cancel: [Function: Cancel],
CancelToken: [Function: CancelToken] { source: [Function: source] },
isCancel: [Function: isCancel],
all: [Function: all],
spread: [Function: spread],
default: [Circular *1]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const axios = require('axios');
const instance = axios.create(); // 默认参数 defaults
console.log(instance.defaults);
// 输出
{
headers: {
common: { Accept: 'application/json, text/plain, */*' },
delete: {},
get: {},
head: {},
post: { 'Content-Type': 'application/x-www-form-urlencoded' },
put: { 'Content-Type': 'application/x-www-form-urlencoded' },
patch: { 'Content-Type': 'application/x-www-form-urlencoded' }
},
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[Axios/adapters/http.js] 中可以看出,NodeJS中axios的实现是基于http或者https模块来发起请求的
[Axios/adapters/xhr.js] 浏览器中axios的实现是对XMLhttpRequest进行封装
# response:

# 封装axios
# 类型声明
# Axios拦截器中的config
export interface InternalAxiosRequestConfig<D = any> extends AxiosRequestConfig<D> {
headers: AxiosRequestHeaders;
}
2
3
# Axios取消请求
使用 Axios 发送的请求可以取消,这对于在组件卸载或其他情况下取消不再需要的请求非常有用,以避免浪费资源和处理不必要的响应。你可以使用 Axios 提供的 CancelToken 来实现请求取消。以下是如何取消 Axios 请求的一般步骤:
- 首先,你需要导入 Axios 库并创建一个 CancelToken 实例:
import axios from 'axios';
const source = axios.CancelToken.source();
2
3
- 然后,在发送请求时,将
cancelToken选项设置为 CancelToken 实例的token属性:
axios.get('/api/data', {
cancelToken: source.token,
})
.then(response => {
// 处理响应
})
.catch(error => {
if (axios.isCancel(error)) {
// 请求已取消
} else {
// 处理其他错误
}
});
2
3
4
5
6
7
8
9
10
11
12
13
- 若要取消请求,调用 CancelToken 实例的
cancel方法:
source.cancel('请求取消的原因');
完整的代码示例:
import axios from 'axios';
const source = axios.CancelToken.source();
axios.get('/api/data', {
cancelToken: source.token,
})
.then(response => {
// 处理响应
})
.catch(error => {
if (axios.isCancel(error)) {
console.log('请求已取消', error.message);
} else {
console.log('处理其他错误', error);
}
});
// 在需要时取消请求
source.cancel('请求取消的原因');
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
这将取消发送给 /api/data 的请求。当调用 source.cancel 时,Axios 会捕获请求并将其标记为已取消。在请求的 .catch 部分,你可以检查是否请求被取消,然后采取适当的措施。
这是一种有效的方式来取消 Axios 请求,但请确保在适当的时机取消请求,以避免不必要的网络请求。通常,可以在组件卸载、路由切换或其他需要取消请求的情况下执行取消操作。
这里调用source.cancel是取消所有请求吗还是取消单一请求?
请注意,source.cancel 调用将取消使用相同 CancelToken 实例的所有请求,而不是单一请求。这是因为 CancelToken 实例是可重复使用的,它可以用于多个请求
# 使用AbortController并封装之
export const getRequest = (controller: AbortController) =>
request({
url: 'http://127.0.0.1:3000/route',
method: 'get',
signal: controller.signal
}); // request是封装的axios实例
2
3
4
5
6
<script setup lang="ts">
/**
* 用来判断是否发出了请求
*/
let HAS_REQUEST = false;
let controller = new AbortController();
const handleRequest = async () => {
HAS_REQUEST = true;
let res = await getRequest(controller);
console.log('res: ', res);
HAS_REQUEST = false;
};
const cancelRequest = () => {
if (HAS_REQUEST) {
controller.abort();
controller = new AbortController();
console.log('请求被取消了!');
}
};
</script>
<template>
<div>
<button @click="handleRequest">发起请求</button>
<button @click="cancelRequest">取消请求</button>
</div>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
关于错误捕获的封装
取消请求会发出一个未捕获的CanceledError错误并在控制台输出,可在响应拦截器中捕获并处理
service.interceptors.response.use(
(response) => {
if (response.status === 200) {
return response.data;
}
},
(err) => {
Promise.reject(err).catch((err) => {
if (axios.isCancel(err)) {
console.log('Request canceled', err.message);
} else console.error('Request failed', err);
});
}
);
2
3
4
5
6
7
8
9
10
11
12
13
14
封装axios后,每个接口定义为一个函数,如下:
export const getAutoCode = (): Promise<{ body: any; code: number }> => axios.get("/captcha");这样每个接口都需要定义返回类型,感觉比较麻烦,有什么较好的解决方法吗
使用 TypeScript 的泛型来减少类型重复定义
// 使用通用的请求函数
const getAutoCode = () => request<{ body: any; code: number }>('/captcha');
const getUserInfo = () => request<{ name: string; age: number }>('/user/info');
2
3
4
# qs模块的arrayFormat
在 qs 模块中,arrayFormat 选项用于控制数组的序列化方式。有三个可用的选项值:
- "indices"(默认值):使用索引形式的数组序列化,例如
foo[0]=bar&foo[1]=baz。 - "brackets":使用方括号形式的数组序列化,例如
foo[]=bar&foo[]=baz。 - "repeat":使用重复键形式的数组序列化,例如
foo=bar&foo=baz。
const params = {
foo: ['bar', 'baz']
};
const queryString = qs.stringify(params, { arrayFormat: 'brackets' });
2
3
4
5
export function getBoardList(params: any) {
const url = `/api/system/notice/list` + qs.stringify(params)
return axios.get(url, {
params: qs.stringify(params)
})
}
2
3
4
5
6
这么写为什么不对?
核心原因是:axios.get 里的 params 期望的是一个对象,而不是已经 stringify 好的字符串。
正确的做法:
export function getBoardList(params: any) {
const url = `/api/system/notice/list`
return axios.get(url, {
params: params,
paramsSerializer: (params) => {
return qs.stringify(params)
}
})
}
2
3
4
5
6
7
8
9