TypeScript项目中Axios的封装

目录

前言

一、axios中的常见类型

[1. AxiosInstance](#1. AxiosInstance)

[2. AxiosRequestConfig](#2. AxiosRequestConfig)

[3. AxiosResponse](#3. AxiosResponse)

[4. AxiosError](#4. AxiosError)

二、axios封装步骤

三、封装后的完整代码

[1. 基础封装](#1. 基础封装)

[2. 高级封装](#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 的类型定义文件)

TypeScript 复制代码
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实例。

TypeScript 复制代码
// 导入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实例,也可以在实例中添加其他自定义的方法和属性。此外,高级封装还将请求方法统一封装在一个类中,结构更加清晰,易于维护和扩展。

TypeScript 复制代码
// 先创建一个类,给类添加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",
});

​

相关推荐
Omics Pro8 分钟前
~30,000+引用!理论2005,R包2008,多组学集成AI增强
开发语言·数据库·人工智能·算法·机器学习·自然语言处理·r语言
小道士写程序17 分钟前
Windows Rust 环境安装指导
开发语言·windows·rust
xh didida18 分钟前
Linux -- 进程概念
linux·服务器·开发语言·c++
爱吃香菜的初学者18 分钟前
十三.Linux——信号量
linux·运维·服务器·开发语言
凉茶钱25 分钟前
【C++】string 常用函数详解
开发语言·c++·string
Wang's Blog36 分钟前
Java框架 SpringCloud 快速入门: 从服务拆分到注册中心的落地路线
java·开发语言·spring cloud
孔令飞44 分钟前
Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中
前端
可乐鸡翅yeah_1 小时前
hls.js 缓冲区参数 maxBufferLength、maxBufferSize 通俗讲解与业务调参
开发语言·javascript·ios·音视频·safari·m3u8
Wang's Blog1 小时前
Java框架 SpringCloud 快速入门: 全局过滤器(GlobalFilter)自定义鉴权
java·开发语言·spring cloud
白山编程大哥1 小时前
C语言篇:可变参数函数
c语言·开发语言