Axios 拦截器(Interceptors)允许你在请求发出之前或响应接收之后执行一些操作。它们对于统一处理请求和响应(如添加认证令牌、处理错误等)非常有用。下面是一个简单的示例:
// interceptor.js
import axios from 'axios';
// 请求拦截器,用于添加认证令牌等
const requestInterceptor = axios.interceptors.request.use(
config => {
// 这里可以添加你的请求处理逻辑
return config;
},
error => {
// 这里处理请求过程中发生的错误
return Promise.reject(error);
}
);
// 响应拦截器,用于处理服务器返回的状态码和数据格式
const responseInterceptor = axios.interceptors.response.use(
response => {
// 这里可以处理响应数据,例如统一的数据格式化
return response;
},
error => {
// 这里处理响应过程中发生的错误,例如状态码检查
return Promise.reject(error);
}
);
// 当不再需要这些拦截器时,可以这样解除注册
function removeInterceptors() {
axios.interceptors.request.eject(requestInterceptor);
axios.interceptors.response.eject(responseInterceptor);
}
export default {
removeInterceptors,
};
那么如何优雅地管理 Axios 拦截器呢?
注册拦截器
// 注册请求拦截器
axios.interceptors.request.use()
// 注册响应拦截器
axios.interceptors.response.use()
移除拦截器
当不再需要特定拦截器时,要移除它,以避免内存泄漏和不必要的处理。
// 移除请求拦截器
axios.interceptors.request.eject()
// 移除响应拦截器
axios.interceptors.response.eject()
组织代码
将拦截器相关的代码放在单独的模块或文件中,以便于管理和维护。对于复杂的逻辑,可以拆分成多个小函数,每个函数负责一个特定的任务。
// complexInterceptor.js
import axios from 'axios';
// 这个函数负责添加认证令牌
function addAuthToken() {
return function (config) {
if (localStorage.getItem('token')) {
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
}
return config;
};
}
// 这个函数负责格式化请求数据
function formatRequestData() {
return function (config) {
// 可以根据需要对 config.data 进行转换
if (config.method === 'POST' && config.url.endsWith('/someSpecialEndpoint')) {
config.data = JSON.stringify(config.data);
}
return config;
};
}
// 这个函数负责格式化响应数据
function formatResponseData() {
return function (response) {
// 可以根据需要对 response.data 进行转换
if (response.config.url.endsWith('/anotherSpecialEndpoint')) {
response.data = JSON.parse(response.data);
}
return response;
};
}
// 这个函数负责处理请求过程中出现的错误
function handleRequestError() {
return function (error) {
console.error('Request failed:', error);
return Promise.reject(error);
};
}
// 这个函数负责处理响应过程中出现的错误
function handleResponseError() {
return function (error) {
if (error.response) {
// 这里可以处理各种 HTTP 状态码
switch (error.response.status) {
case 401:
// 未授权,可能需要重新登录
break;
case 403:
// 禁止访问,权限不足
break;
case 500:
// 服务器内部错误
break;
default:
// 其他错误处理
break;
}
} else if (error.request) {
// 这里处理网络问题,例如请求已发送但没有收到响应
console.error('Network error:', error.request);
} else {
// 这里处理其他类型的错误,例如配置请求时出错
console.error('Error in request configuration:', error.message);
}
return Promise.reject(error);
};
}
export default function registerInterceptor() {
const requestInterceptor = axios.interceptors.request.use(
addAuthToken(),
handleRequestError()
);
const responseInterceptor = axios.interceptors.response.use(
formatResponseData(),
handleResponseError()
);
// 返回一个函数以取消拦截器注册
return () => {
axios.interceptors.request.eject(requestInterceptor);
axios.interceptors.response.eject(responseInterceptor);
};
}
错误处理
- 在拦截器中提供错误处理逻辑,例如,当发生错误时返回一个
Promise.reject()
。 - 在调用链的最后,使用
.catch()
处理所有未在拦截器中处理的错误。
优先级和顺序
- 考虑拦截器的注册顺序,因为它们的执行顺序就是注册的顺序。
- 如果有多个拦截器,决定它们之间的优先级,以便于正确处理请求和响应。
可配置性和可重用性
- 创建可配置的拦截器,以便于根据不同情况动态配置行为。
- 如果有多个相似的拦截器,考虑抽象出一个通用的拦截器,通过参数来配置其行为。
测试
- 写单元测试来保证拦截器的行为符合预期。
- 测试拦截器是否正确地处理了各种情况,如成功请求、失败请求等。
评论区