目录

前言

一、axios中的常见类型

1. AxiosInstance

2. AxiosRequestConfig

3. AxiosResponse

4. AxiosError

二、axios封装步骤

三、封装后的完整代码

1. 基础封装

2. 高级封装


前言

为了实现统一的网络请求处理和管理,在日常开发中我们常常封装 axios,来实现统一配置、设置请求拦截器和响应拦截器、错误处理等。

TypeScript可以给项目提供类型检查和类型推导,axios请求回来的数据也会受其检查。本文将提供axios结合ts写法的封装步骤和代码。

一、axios中的常见类型

1. AxiosInstance

表示axios请求的配置选项,包括URL、方法、头部、参数等。

2. AxiosRequestConfig

表示一个axios实例的类型,可以用于创建自定义配置的axios实例。

3. AxiosResponse

表示axios响应的数据结构,包括状态码、响应头和响应数据。

4. AxiosError

表示axios请求发生错误时的错误对象,包括错误消息、请求配置和响应信息(如果有)。

注意:如果没有跟类型,ts也会自动推到成相应类型。可以不写,但不能错写。

二、axios封装步骤

1. 安装依赖

在项目根目录下,使用 npm 或 yarn 命令安装 axios 和 @types/axios(用于提供 axios 的类型定义文件)

pnpm install axios @types/axios

2. 创建封装文件

在项目中创建一个新的文件,例如 request.ts,用于封装 axios。可以根据项目需求结构化地组织这些文件。文件名根据个人习惯来,大都取 axios 、request 、http等。

3. 导入 axios

request.ts 文件中导入 axios 模块。

4. 添加默认配置

根据需要,在请求方法中设置默认的请求头、超时时间、响应数据格式等配置项。

5. 定义返回的数据类型

根据后端返回的数据,设置统一的请求结果接口。

6. 添加拦截器

如果需要使用拦截器,可以在 api.ts 文件中定义请求拦截器和响应拦截器,并注册到 axios 中。

7. 封装请求方法

根据项目需求,定义请求方法,例如 GET、POST、PUT、DELETE 等。可以使用泛型来指定请求和响应的数据类型,增加类型安全性。

8. 导出方法/实例

在 request.ts 文件末尾,将封装的请求方法进行导出。

三、封装后的完整代码

1. 基础封装

使用对象字面量方式创建一个单例的axios实例。

// 导入axios和所需的类型
import axios, { AxiosInstance, AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios'

// 默认配置
const service: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE || '/' // 设置API的基本URL,默认为根路径
})

// 请求拦截器,对请求配置进行一些处理或设置
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    return config
  },
  (error: AxiosError) => {
    return Promise.reject(error)
  }
)

// 响应拦截器,对响应结果进行处理或判断
service.interceptors.response.use(
  (response: AxiosResponse) => {
    if (response.status === 200) {
      return response.data
    }
    return Promise.reject() // 如果响应状态不是200,则返回一个拒绝的Promise
  },
  (error: AxiosError) => {
    return Promise.reject(error)
  }
)

export default service // 导出封装好的axios实例

// 定义结果接口Result
export interface Result<T = unknown> {
  message: string
  code: number
  data: T

  [key: string]: any // 其他任意属性
}

export const http = {
  // 发送GET请求的方法,可指定数据类型T,并返回一个Promise对象,其值为Result<T>类型
  get<T = any>(url: string, data?: object): Promise<Result<T>> {
    return service.get<T, Result<T>>(url, data);
  },

  // 发送POST请求的方法,同样可指定数据类型T,并返回一个Promise对象
  post<T = any>(url: string, data?: object): Promise<Result<T>> {
    return service.post<T, Result<T>>(url, data);
  },

  // 发送PUT请求的方法,同样可指定数据类型T,并返回一个Promise对象
  put<T = any>(url: string, data?: object): Promise<Result<T>> {
    return service.put<T, Result<T>>(url, data);
  },

  // 发送DELETE请求的方法,同样可指定数据类型T,并返回一个Promise对象
  delete<T = any>(
    url: string
  ): Promise<Result<T>> {
    return service.delete<T, Result<T>>(url);
  },
};

2. 高级封装

相比基础封装,高级封装通过类的方式来创建实例,并将请求方法封装在类的原型上。

相比之下,这种方法更加灵活,可以创建多个不同配置的axios实例,也可以在实例中添加其他自定义的方法和属性。此外,高级封装还将请求方法统一封装在一个类中,结构更加清晰,易于维护和扩展。

// 先创建一个类,给类添加1个属性 instance代表axios的实例  构造函数传递配置 config配置比如全局的baseURL timeout
​
import axios from "axios";
import type {
  AxiosInstance,
  AxiosError,
  AxiosResponse,
  AxiosRequestConfig,
} from "axios";
​
// interface Result<T = any> {
//   data: T;
//   success: boolean;
// }
​
class Request {
  // 限制创建的实例必须是axios的实例
  private instance: AxiosInstance;
  // 这个config是不能乱写的,axios对创建的配置有限制的
  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create(config);
​
    // 接下来配置axios实例身上的全局配置,比如拦截器
    this.instance.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        return config;
      },
      (error: AxiosError) => {
        return Promise.reject(error);
      }
    );
​
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        return response.data;
      },
      (error: AxiosError) => {
        return Promise.reject(error);
      }
    );
  }
​
  // 公共方法,因为不知道返回值的类型
  fetchData<T>(options: AxiosRequestConfig): Promise<T> {
    // 将私有的instance上面发请求的操作,封装到这个实例方法request中,这个方法的返回值应该是一个promise对象
    return new Promise((resolve, reject) => {
      this.instance
        .request<any, T>(options)
        .then((res) => {
          resolve(res);
        })
        .catch((err) => {
          reject(err);
        });
    });
  }
​
  // 调用上面封装的实例方法request,来实现get / post / delete / put 方法的快捷调用
  get<T>(options: AxiosRequestConfig): Promise<T> {
    return this.fetchData<T>({ ...options, method: "GET" });
  }
​
  post<T>(options: AxiosRequestConfig): Promise<T> {
    return this.fetchData({ ...options, method: "POST" });
  }
​
  put<T>(options: AxiosRequestConfig): Promise<T> {
    return this.fetchData({ ...options, method: "PUT" });
  }
​
  delete<T>(options: AxiosRequestConfig): Promise<T> {
    return this.fetchData({ ...options, method: "DELETE" });
  }
}
​
// 到处新new出来的实例
export const http = new Request({
  baseURL: "https://mock.mengxuegu.com/mock/6323def2b4c53348ed2bc5d7/example",
});

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐