TypeScript 项目中,封装一个详细的 axios
请求工具可以提高代码的可维护性、可重用性,并让请求逻辑与业务逻辑分离。以下是一个详细的封装示例,包括请求拦截器、响应拦截器、错误处理、以及类型定义。
1. 安装 Axios
首先,确保你已安装 axios
和 axios
类型定义。
npm install axios
npm install --save-dev @types/axios
2. 封装 Axios 请求工具
在项目中创建一个新的文件 src/utils/axios.ts
来封装所有请求相关的逻辑。
// src/utils/axios.ts
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
// 定义通用的返回数据结构
interface ApiResponse<T = any> {
code: number;
message: string;
data: T;
}
class AxiosRequest {
private axiosInstance: AxiosInstance;
constructor() {
this.axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL, // 基础URL,可以在环境变量中配置
timeout: 5000, // 请求超时
headers: {
'Content-Type': 'application/json',
},
});
// 请求拦截器
this.axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 可以在请求前做一些操作,例如加入 token
const token = localStorage.getItem('token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
},
(error: AxiosError) => {
return Promise.reject(error);
}
);
// 响应拦截器
this.axiosInstance.interceptors.response.use(
(response: AxiosResponse<ApiResponse>) => {
// 可以处理一些通用的响应数据
const { code, message, data } = response.data;
if (code === 0) {
return data; // 返回正常数据
} else {
// 根据不同的 `code` 进行错误处理
return Promise.reject(new Error(message || '未知错误'));
}
},
(error: AxiosError) => {
// 统一错误处理
let errorMessage = '请求失败';
if (error.response) {
errorMessage = error.response.data.message || '服务器异常';
} else if (error.request) {
errorMessage = '网络异常';
} else {
errorMessage = error.message;
}
return Promise.reject(new Error(errorMessage));
}
);
}
// 封装 GET 请求
public get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.axiosInstance
.get<ApiResponse<T>>(url, config)
.then((response) => response);
}
// 封装 POST 请求
public post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return this.axiosInstance
.post<ApiResponse<T>>(url, data, config)
.then((response) => response);
}
// 封装 PUT 请求
public put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return this.axiosInstance
.put<ApiResponse<T>>(url, data, config)
.then((response) => response);
}
// 封装 DELETE 请求
public delete<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.axiosInstance
.delete<ApiResponse<T>>(url, config)
.then((response) => response);
}
}
// 创建一个 AxiosRequest 实例
const axiosRequest = new AxiosRequest();
export default axiosRequest;
3. 请求使用示例
在 Vue 组件中,可以直接导入并使用封装好的请求工具。
// src/views/Example.vue
<template>
<div>
<button @click="fetchData">获取数据</button>
<div v-if="error" class="error">{{ error }}</div>
<div v-if="data">
<pre>{{ data }}</pre>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import axiosRequest from '@/utils/axios';
export default defineComponent({
name: 'Example',
setup() {
const data = ref<any>(null);
const error = ref<string>('');
const fetchData = async () => {
try {
const response = await axiosRequest.get('/api/endpoint'); // 调用 GET 请求
data.value = response;
} catch (err) {
error.value = (err as Error).message;
}
};
return {
data,
error,
fetchData,
};
},
});
</script>
<style scoped>
.error {
color: red;
}
</style>
4. 配置环境变量
确保在 .env
文件中配置基础的 API URL:
VITE_API_BASE_URL=https://your-api-url.com
5. 代码解释
- 请求拦截器:在请求发送之前,可以为请求添加授权信息(如 token)。也可以处理其他全局请求配置。
- 响应拦截器:所有的响应数据都会经过拦截器处理,统一检查返回的
code
,如果为0
表示成功,否则会抛出错误。 - 错误处理:无论是请求错误还是响应错误,都会被统一捕获并返回可读的错误信息。
- 请求方法封装:提供了
GET
、POST
、PUT
和DELETE
方法封装,可以在不同的接口请求中使用。
通过这种方式,你的 Axios 请求将更加模块化、易于维护,并且在遇到问题时能够快速定位和处理错误。