Axions - 拦截器
# Axios 拦截器
Axios 拦截器(Interceptors)是一个非常实用的功能,允许在请求或响应被 then
或 catch
处理之前拦截它们。通过拦截器,我们可以在请求发送前或响应返回后执行额外的逻辑,如为每个请求添加认证 Token、统一处理错误响应、记录日志等。拦截器分为三类:全局拦截器、请求拦截器 和 响应拦截器。
# 一、全局拦截器
全局拦截器会影响所有通过 Axios 实例发出的请求。它通常用于配置每个请求都需要的通用设置,如 API 的基础 URL、默认请求头、超时时间等。
import axios from 'axios';
// 创建一个 Axios 实例
const axiosInstance = axios.create({
baseURL: 'https://api.example.com', // 所有请求的基础 URL
timeout: 10000, // 请求超时时间设置为 10 秒
headers: {
'Content-Type': 'application/json', // 默认请求头,指定内容类型
}
});
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
关键点:
axios.create()
:创建一个带有全局配置的 Axios 实例,用于在项目中复用。baseURL
:配置请求的基础 URL,所有请求都会基于此 URL 进行拼接。timeout
:指定请求的超时时间,超时后请求会自动取消。headers
:设置请求的默认头部信息,如Content-Type
。
# 二、请求拦截器
请求拦截器在请求发出前被触发,可以用来修改请求配置、添加额外的请求信息(如 Token),或者进行一些全局的前置处理。这种拦截器的常见用途包括在请求头中添加认证信息、为所有请求统一添加公共参数、记录日志等。
// 添加请求拦截器
axiosInstance.interceptors.request.use(
config => {
// 请求发送前的处理逻辑
// 从本地存储中获取 Token
const token = localStorage.getItem('token');
// 如果存在 Token,则将其添加到请求头部
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
// 在这里添加公共参数、修改请求配置等
// 例如为所有请求添加一个语言参数 'lang'
config.params = {
...config.params, // 保留已有的参数
lang: 'en' // 添加公共的 'lang' 参数
};
// 打印当前请求的配置(用于调试)
console.log('请求配置:', config);
// 返回修改后的配置对象,以继续请求的流程
return config;
},
error => {
// 请求错误处理
console.error('请求错误:', error);
// 返回 Promise.reject 以确保错误被捕获
return Promise.reject(error);
}
);
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
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
关键点:
config
:请求的配置对象,可以动态修改请求头、参数等。Authorization
:通常用于在请求头中携带认证信息(如 Token)。config.params = { ...config.params, lang: 'en' };
:使用 JavaScript 的展开语法,将现有的查询参数展开,并添加一个新的公共参数lang: 'en'
。这适用于需要在所有请求中统一传递某些参数的场景。
# 三、响应拦截器
响应拦截器在收到响应数据后触发,可以用来统一处理响应数据、拦截错误响应等。常见的应用场景包括根据状态码进行错误处理、全局处理错误信息等。
// 添加响应拦截器
axiosInstance.interceptors.response.use(
response => {
// 处理成功的响应数据
if (response.status === 200) {
return response.data; // 直接返回数据,简化后续处理
} else {
// 非 200 状态码处理
return Promise.reject(new Error('请求失败,状态码:' + response.status));
}
},
error => {
// 响应错误处理
if (error.response) {
// 根据状态码处理不同的错误
switch (error.response.status) {
case 401:
console.error('未授权,请重新登录');
break;
case 403:
console.error('权限不足,拒绝访问');
break;
case 500:
console.error('服务器内部错误');
break;
default:
console.error('其他错误:', error.response.status);
}
} else if (error.request) {
// 请求已发送但未收到响应
console.error('请求超时或网络异常');
} else {
// 处理其他错误
console.error('请求出错:', error.message);
}
return Promise.reject(error); // 返回 Promise.reject 以确保错误被捕获
}
);
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
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
关键点:
response
:响应对象,可以在这里对返回的数据进行统一预处理。- 常见用法:根据状态码处理错误、记录错误日志、处理网络异常等。
# 四、拦截器完整示例
您提到的场景非常常见,通常在本地存储(如 localStorage
或 sessionStorage
)中保存的是后端返回的用户信息对象,里面包括 token
以及用户的其他信息。我们可以在请求拦截器中提取这个信息,并在发送请求时将 token
添加到请求头中。
这里是根据这种需求重新编写的代码:
import axios from 'axios';
import router from '@/router';
import { Message } from 'element-ui'; // 引入 Element UI 的 Message 模块
// 创建 Axios 实例
const axiosInstance = axios.create({
baseURL: 'https://api.example.com', // 全局基础 URL
timeout: 10000, // 设置请求超时时间为 10 秒
headers: {
'Content-Type': 'application/json' // 设置默认的内容类型为 JSON
}
});
// 请求拦截器
axiosInstance.interceptors.request.use(
config => {
// 从本地存储中获取缓存的用户信息
const user = JSON.parse(localStorage.getItem('user') || '{}');
// 如果用户信息存在,并且包含 token
if (user && user.token) {
config.headers['Authorization'] = `Bearer ${user.token}`; // 为每个请求添加 Authorization 头
}
// 例如可以统一添加公共参数
config.params = { ...config.params, lang: 'en' }; // 为所有请求添加语言参数
console.log('请求拦截器配置:', config);
return config; // 返回修改后的请求配置对象
},
error => {
// 请求错误处理
console.error('请求错误:', error);
Message.error('请求发送失败,请检查网络或稍后再试'); // 添加错误提示
return Promise.reject(error); // 确保错误被捕获
}
);
// 响应拦截器
axiosInstance.interceptors.response.use(
response => {
// 在响应数据返回之前做一些处理
if (response.status === 200) {
console.log('响应成功:', response);
return response.data; // 直接返回数据,简化业务代码
} else {
Message.error('请求失败,状态码:' + response.status); // 添加错误提示
return Promise.reject(new Error('请求失败,状态码:' + response.status));
}
},
error => {
// 响应错误处理
if (error.response) {
// 服务器返回的错误,根据状态码进行不同处理
const status = error.response.status;
switch (status) {
case 401:
Message.error('登录已过期,请重新登录');
// 清除本地存储中的用户信息
localStorage.removeItem('user');
router.push('/login'); // 跳转到登录页面
break;
case 403:
Message.error('权限不足,拒绝访问');
break;
case 404:
Message.error('请求资源未找到');
break;
case 500:
Message.error('服务器内部错误,请稍后再试');
break;
default:
Message.error('请求出错,状态码:' + status);
}
} else if (error.request) {
// 请求已发送但未收到响应
Message.error('请求超时或网络异常');
} else {
// 其他错误处理
Message.error('请求出错:' + error.message);
}
return Promise.reject(error); // 确保错误被捕获
}
);
// 导出 Axios 实例,供业务代码使用
export default axiosInstance;
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
关键点说明:
本地存储用户信息:
- 我们假设在本地存储中保存的是一个包含
token
和其他用户信息的对象。比如:
{ "username": "user123", "token": "your-jwt-token" }
1
2
3
4这个对象保存在
localStorage
中的user
键下。- 我们假设在本地存储中保存的是一个包含
在请求拦截器中添加
Authorization
头:- 在请求拦截器中,我们首先从本地存储获取用户信息,并检查是否包含
token
。如果存在,则将其添加到请求头中。
- 在请求拦截器中,我们首先从本地存储获取用户信息,并检查是否包含
处理未授权状态:
- 如果响应状态码为
401
,表示未授权,我们将清除本地存储中的用户信息,并跳转到登录页面。
- 如果响应状态码为
更友好的错误提示:
- 每个错误处理分支中都添加了 Element UI 的
Message.error
,确保用户可以清楚了解当前发生的错误。
- 每个错误处理分支中都添加了 Element UI 的
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08