当前位置: 首页 > article >正文

TypeScript 封装 Axios 1.7.7

随着Axios版本的不同,类型也在改变,以后怎么写类型?
在这里插入图片描述
在这里插入图片描述

yarn add axios

1. 封装Axios

将Axios封装成一个类,同时重新封装request方法

  • 重新封装request有几个好处:
    1. 所有的请求将从我们定义的requet请求中发送,这样以后更换Axios工具,只需要将request方法重写就可以。
    2. 便于对请求的请求体和返回数据做拦截
    3. 方便统一配置请求的config
  • 最基础版本
import axios from "axios";
import type { AxiosInstance } from "axios";

class MyAxios {
  instance: AxiosInstance;
  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create(config);
  }
// 重新封装axios的request方法
  async request(config: AxiosRequestConfig) {
    return await this.instance.reques(config)
  }
}
export default MyAxios;
  • 发送请求
import MyAxios from "./request";
import { BASE_URL, TIME_OUT} from "./config"; // 配置文件

const myRequest1 = new MyAxios({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
});

myRequest1
  .request({
    url: "/XXXXX",
  })
  .then((res) => {
    // res为成功后返回的结果
  });

2. 加入全局拦截器

  • 加入全局拦截器后封装的Axios,调用方法与上面保持一致
import axios from "axios";
import type { AxiosInstance } from "axios";

class MyAxios {
  instance: AxiosInstance;
  constructor(config: AxiosRequestConfig) {
  	// 创建axios的实例
    this.instance = axios.create(config);
    // 全局请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // "全局请求拦截器:请求成功");
        return config;
      },
      (error) => {
        // ("全局请求拦截器:请求失败");
        return error;
      }
    );
    // 全局响应拦截器
    this.instance.interceptors.response.use(
      (res) => {
       // ("全局响应拦截器:响应成功");
       // res中含有axios中的很多东西,res.data :服务器返回的结果,
        return res.data;
      },
      (error) => {
        // ("全局响应拦截器:响应失败");
        return error;
      }
    );
  }

  async request(config: AxiosRequestConfig) {
    return await this.instance.request(config)
  }
}

export default MyAxios;
  • 发送请求
import MyAxios from "./request";
import { BASE_URL, TIME_OUT} from "./config"; // 配置文件

const myRequest1 = new MyAxios({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
});

myRequest1
  .request({
    url: "/XXXXX",
  })
  .then((res) => {
    // res变成了服务器发送会的数据,全局响应拦截器把Axios带的一些数据去掉了
  });

3. 加入域拦截器

域拦截器是我自己想的名字,也可以说是实例拦截器
在实例中定义拦截方法

  1. 拦截的范围是一个baseURL,所以我称它为域拦截
  2. 因为定义在一个new MyAxios实例中,也可以说是实例拦截器
  • 给拦截器定义类型
import type { AxiosRequestConfig } from "axios";

// 自定义拦截器中的方法的类型
interface interceptorsFunction {
  requestOnFulfilled?: (config: any) => any; // 请求成功
  requestOnRejected?: (error: any) => any; //  请求失败
  responseOnFulfilled?: (res: any) => any; //  响应成功
  responseOnRejected?: (error: any) => any; // 响应失败
}
// 自定义拦截器类型。这里扩展了AxiosRequestConfig类型
interface MyAxiosRequestConfig extends AxiosRequestConfig {
  MyInterceptors?: interceptorsFunction;
}

export { MyAxiosRequestConfig };
  • 在实例中实现拦截器的方法
import MyAxios from "./request";
import { BASE_URL, TIME_OUT } from "./config";
import type { MyAxiosRequestConfig } from "./type";

const myRequest2 = new MyAxios({
  baseURL: BASE_URL,	
  timeout: TIME_OUT,
  // 域拦截器。给axios发送的自定义拦截器需要执行的功能
  MyInterceptors: {
    requestOnFulfilled: (config) => {
      // ("自定义请求拦截器:请求成功");
      return config
    },
    requestOnRejected: (error) => {
      // ("自定义请求拦截器:请求失败");
      return error
    },
    responseOnFulfilled: (res) => {
      // ("自定义响应拦截器:响应成功");
      return res
    },
    responseOnRejected: (error) => {
      // ("自定义响应拦截器:响应失败");
      return error
    }
  }
})
// 发送请求
myRequest.myRequest2
  .request({
    url: "XXXXXX",
  })
  .then((res) => {
    // (res);
  });
  • 封装Axois
import axios from "axios";
import type { AxiosInstance } from "axios";
// 导入自定义拦截器的类型
import type { MyAxiosRequestConfig } from "./type";

class MyAxios {
  instance: AxiosInstance;
  constructor(config: MyAxiosRequestConfig) {
    this.instance = axios.create(config);
    // 全局请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // ("全局请求拦截器:请求成功");
        return config;
      },
      (error) => {
        // ("全局请求拦截器:请求失败");
        return error;
      }
    );
    // 全局响应拦截器
    this.instance.interceptors.response.use(
      (res) => {
        // ("全局响应拦截器:响应成功");
        return res.data;
      },
      (error) => {
        // ("全局响应拦截器:响应失败");
        return error;
      }
    );
    // 请求中自定义的拦截器:实例的拦截器
    // 判断config中是否有自定义的拦截器
    if (config.MyInterceptors) {
    	// 把config中传过来的方法,绑定到实例上
      this.instance.interceptors.request.use(
        config.MyInterceptors.requestOnFulfilled,
        config.MyInterceptors.requestOnRejected
      );
      this.instance.interceptors.response.use(
        config.MyInterceptors.responseOnFulfilled,
        config.MyInterceptors.responseOnRejected
      );
    }
  }
  async request(config: AxiosRequestConfig<T>) {
    return await this.instance.request(config)
  }
}

export default MyAxios;

4. 关于类型

  requestOnFulfilled?: (config: any) => any; // 请求成功

定义拦截器类型中requestOnFulfilled类型,看的教学视频中config的类型是AxiosRequestConfig,我设置后死活报错,看了一下axios的类型定义文件中这里是InternalAxiosRequestConfig,这里就涉及axios的版本问题了,所以我觉得还是any安全,万一明天更新版本又换了类型,这个代码就不通用了

在这里插入图片描述

5. 一次性拦截器

  • 这又是我自己起的名字,这个拦截器针对具体的一个请求

例如:域 http:// 10.1.2.3:8000下面有很多资源,比如有/api/img、/api/text,一次性拦截器就是针对域下面的资源的,可能/api/img需要拦截器工作,而/api/text不需要拦截器,所以每个资源对拦截器的需求和功能是不一样的

  • 封装Axios,主要是对request请求的改动,其他地方没有改动,省略代码,这个拦截器虽然是起到了拦截器的效果,其实就是引入了一段代码
import axios from "axios";
import type { AxiosInstance } from "axios";
// 导入自定义拦截器的类型
import type { MyAxiosRequestConfig } from "./type";

class MyAxios {
  instance: AxiosInstance;
  constructor(config: MyAxiosRequestConfig) {
    this.instance = axios.create(config);
    // 全局请求拦截器

    // 全局响应拦截器

    // 请求中自定义的拦截器:实例的拦截器
  }

  async request(config: MyAxiosRequestConfig) {
  	// config中是否定义了requestOnFulfilled这个方法
    if (config.MyInterceptors?.requestOnFulfilled) {
    // 如果有这个方法,把config对象处理一下
      config = config.MyInterceptors.requestOnFulfilled(config);
    }
    return await this.instance
      .request(config)	// request方法返回Promise
      .then((res) => {	
      	// Promise是成功状态返回的res,如果需要处理就处理一下子
        if (config.MyInterceptors?.responseOnFulfilled) {
          res = config.MyInterceptors.responseOnFulfilled(res);
        }
        return res;
      })
      .catch((error) => {	// Promise是失败状态或者异常,处理一下子
        if (config.MyInterceptors?.responseOnRejected)
          error = config.MyInterceptors.responseOnRejected(error);
        return error;
      });
  }
}

export default MyAxios;
  • 发送请求
const myRequest1 = new MyAxios({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
});
// 发送请求
myRequest1
  .request({
    url: "XXXXXX",
    // 定义一次性拦截器,只对 url: "XXXXX" 起效
    MyInterceptors: {
      requestOnFulfilled: (config) => {
        // ("一次性拦截器,请求成功拦截");
        return config;
      },
      responseOnFulfilled: (res) => {
        // ("一次性拦截器,响应成功拦截");
        return res;
      },
      responseOnRejected: (res) => {
        // ("一次性拦截器,响应失败拦截");
        return res;
      },
    },
  })
  .then((res) => {
    // (res);
  });

  • 拦截器的类型定义与域拦截器中的一样就不重复了

6. 总结

  • 全局拦截器:只要使用Axios发送请求就会执行
  • 域拦截器:对实例中的一个baseURL(http://10.1.2.3:8080)负责
  • 一次性拦截器:对单个request请求负责(/api/img、/api/text)

7. 以下是加上泛型定义和其他请求的Axios封装的完整版本

拦截器的类型定义

// /request/type.ts 文件
import type { AxiosRequestConfig } from "axios";

// 自定义拦截器中的方法的类型
interface interceptorsFunction<T = any> {
  requestOnFulfilled?: (config: any) => any; // 请求成功
  requestOnRejected?: (error: any) => any; //  请求失败
  responseOnFulfilled?: (res: T) => T; //  响应成功
  responseOnRejected?: (error: any) => any; // 响应失败
}
// 自定义拦截器类型
interface MyAxiosRequestConfig<T = any> extends AxiosRequestConfig {
  MyInterceptors?: interceptorsFunction<T>;
}

export type { MyAxiosRequestConfig };

常量的定义

- 这里的cLog是方便调试,不用的时候在这里设置为false就不打印了,打印的东西多了,看的眼花
// /config/index.ts
export const cLog = (message:any)=>{
  // if (process.env.NODE_ENV !== 'production') return
  // if (0) return 
  console.log(message)
}

export const BASE_URL = "http://XXXXXXXXXX"
export const TIME_OUT = 10000

封装后的Axios

// /request/index.ts
import axios from "axios";
import type { AxiosInstance } from "axios";
import { cLog } from "../config";
// 导入自定义拦截器的类型
import type { MyAxiosRequestConfig } from "./type";

class MyAxios {
  instance: AxiosInstance;
  constructor(config: MyAxiosRequestConfig) {
    this.instance = axios.create(config);
    // 全局请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        cLog("全局请求拦截器:请求成功");
        return config;
      },
      (error) => {
        cLog("全局请求拦截器:请求失败");
        return error;
      }
    );
    // 全局响应拦截器
    this.instance.interceptors.response.use(
      (res) => {
        cLog("全局响应拦截器:响应成功");
        return res.data;
      },
      (error) => {
        cLog("全局响应拦截器:响应失败");
        return error;
      }
    );
    // 请求中自定义的拦截器:实例的拦截器
    if (config.MyInterceptors) {
      this.instance.interceptors.request.use(
        config.MyInterceptors.requestOnFulfilled,
        config.MyInterceptors.requestOnRejected
      );
      this.instance.interceptors.response.use(
        config.MyInterceptors.responseOnFulfilled,
        config.MyInterceptors.responseOnRejected
      );
    }
  }

  async request<T = any>(config: MyAxiosRequestConfig<T>) {
    if (config.MyInterceptors?.requestOnFulfilled) {
      config = config.MyInterceptors.requestOnFulfilled(config);
    }
    return await this.instance
      .request<any, T>(config)
      .then((res) => {
        if (config.MyInterceptors?.responseOnFulfilled) {
          res = config.MyInterceptors.responseOnFulfilled(res);
        }
        return res;
      })
      .catch((error) => {
        if (config.MyInterceptors?.responseOnRejected)
          error = config.MyInterceptors.responseOnRejected(error);
        return error;
      });
  }
  get<T = any>(config: MyAxiosRequestConfig<T>) {
    return this.request({ ...config, method: "get" });
  }
  post<T = any>(config: MyAxiosRequestConfig<T>) {
    return this.request({ ...config, method: "post" });
  }
  delete<T = any>(config: MyAxiosRequestConfig<T>) {
    return this.request({ ...config, method: "delete" });
  }
  put<T = any>(config: MyAxiosRequestConfig<T>) {
    return this.request({ ...config, method: "put" });
  }
  patch<T = any>(config: MyAxiosRequestConfig<T>) {
    return this.request({ ...config, method: "patch" });
  }
}

export default MyAxios;

实例Axios

- myRequest1:只有全局拦截器
- myRequest2:有全局拦截器和域拦截器
// index.ts
import MyAxios from "./request";
import { BASE_URL, TIME_OUT, cLog } from "./config";

const myRequest1 = new MyAxios({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
});

const myRequest2 = new MyAxios({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
  // 给axios发送的自定义拦截器需要执行的功能
  MyInterceptors: {
    requestOnFulfilled: (config) => {
      cLog("自定义请求拦截器:请求成功");
      return config
    },
    requestOnRejected: (error) => {
      cLog("自定义请求拦截器:请求失败");
      return error
    },
    responseOnFulfilled: (res) => {
      cLog("自定义响应拦截器:响应成功");
      return res
    },
    responseOnRejected: (error) => {
      cLog("自定义响应拦截器:响应失败");
      return error
    }
  }
})
export default { myRequest1,myRequest2 };

实际发送请求

  • 以上都可以作为固定的使用,下面的部分就是我们每次要发送请求时编写的
// main.js
import myRequest from "../index";
import { cLog } from "../config";

myRequest.myRequest1
  .request({
    url: "XXXXX",
  })
  .then((res) => {
    cLog(res);
  });

myRequest.myRequest2
  .request({
    url: "XXXXX",
  })
  .then((res) => {
    cLog(res);
  });

myRequest.myRequest2
 // 这里的类型是服务器返回数据的类型,感觉复杂这里用any
 // 为什么这里的类型是服务器返回的数据类型?在全局拦截器中返回的是res.data
 // 如果在其他拦截器中没有对res做出改变。这里应该是AxiosResponse类型
  .request<类型>({ 
    url: "XXXXX",
    // 一次性拦截器
    MyInterceptors: {
      requestOnFulfilled: (config) => {
        cLog("一次性拦截器,请求成功拦截");
        return config;
      },
      responseOnFulfilled: (res) => {
        cLog("一次性拦截器,响应成功拦截");
        return res;
      },
      responseOnRejected: (res) => {
        cLog("一次性拦截器,响应失败拦截");
        return res;
      },
    },
  })
  .then((res) => {
    cLog(res);
  });

8. 拦截器的执行顺序

  • 只有全局拦截器
全局请求拦截器:请求成功
全局响应拦截器:响应成功
  • 有全局拦截器和域拦截器
自定义请求拦截器:请求成功
全局请求拦截器:请求成功
全局响应拦截器:响应成功
自定义响应拦截器:响应成功
  • 全局、域、一次性拦截器
一次性拦截器,请求成功拦截
自定义请求拦截器:请求成功
全局请求拦截器:请求成功
全局响应拦截器:响应成功
自定义响应拦截器:响应成功
一次性拦截器,响应成功拦截

9. 目录结构

在这里插入图片描述


http://www.kler.cn/news/329792.html

相关文章:

  • 软件测试面试八股文(含答案+文档)
  • 【yolov8】模型导出----pytorch导出为onnx模型
  • windows美化终端
  • go结构体默认值和校验器(go-defaults、go-validator)
  • 【Redis】主从复制(下)--主从复制原理和流程
  • 【数据分享】2001-2023年我国省市县镇四级的逐月平均气温数据(免费获取/Shp/Excel格式)
  • ubuntu 安装kvm 创建windos虚拟机
  • AMD 矩阵核心
  • 搜维尔科技:使用Xsens动作捕捉系统和ai训练人形机器人模仿人类运动,执行复杂任务
  • docker环境下配置cerbot获取免费ssl证书并自动续期
  • java中有两个list列表,尽量少的去循环
  • 模版and初识vector
  • windows系统电脑上scrcpy源码本地调试
  • Java基础——十二、容器
  • 5G NR物理信号
  • git push 远程仓库 linux版
  • 爬虫——爬虫理论+request模块
  • 【Linux】进程周边之优先级
  • 陶建辉先生荣获 2024 年“中国计算机学会(CCF)杰出工程师奖”
  • Harbor系列之12:对接外部redis和pg数据库的harbor容器化部署
  • C++:采用模板封装顺序表,栈,队列
  • 秋招内推2025--招联金融
  • 【MySQL】聚合函数、group by子句
  • Vue 常用的指令用法
  • “大数据+高职”:VR虚拟仿真实训室的发展前景
  • 2、Objects类(为什么重写 equals方法必须重写 hashCode方法)、无序性+随机性+不可重复性的区别
  • Android Studio 占满C盘快速解决方法
  • Matlab|考虑阶梯式碳交易与供需灵活双响应的综合能源系统优化调度
  • 《向量数据库指南》——非结构化数据挑战升级:如何高效导入向量数据库?
  • Android 开发每日定时任务