Bootstrap

基于TypeScript封装 `axios` 请求工具详解

TypeScript 项目中,封装一个详细的 axios 请求工具可以提高代码的可维护性、可重用性,并让请求逻辑与业务逻辑分离。以下是一个详细的封装示例,包括请求拦截器、响应拦截器、错误处理、以及类型定义。

1. 安装 Axios

首先,确保你已安装 axiosaxios 类型定义。

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 表示成功,否则会抛出错误。
  • 错误处理:无论是请求错误还是响应错误,都会被统一捕获并返回可读的错误信息。
  • 请求方法封装:提供了 GETPOSTPUTDELETE 方法封装,可以在不同的接口请求中使用。

通过这种方式,你的 Axios 请求将更加模块化、易于维护,并且在遇到问题时能够快速定位和处理错误。

;