TypeScript 封装 Axios 1.7.7

news2024/11/21 2:29:57

随着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 { 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://codercba.com:8000"
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.coloradmin.cn/o/2183248.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WebRTC入门

主要参考资料&#xff1a; WebRTC 在 ESP32 系列硬件平台上的实现: https://www.bilibili.com/video/BV1AEHseWEda/?spm_id_from333.337.search-card.all.click&vd_sourcedd284033cd0c4d1f3f59a2cd40ae4ef9 火山 RTC豆包大模型&#xff0c;给用户体验装上银色子弹: https:…

第九篇——数列和级数(二):传销骗局的数学原理

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 文章不长&#xff0c;但是道理深刻&#xff1b;相邻两个数的差值&#xf…

Prompt 模版解析:诗人角色的创意引导与实践

Prompt 模版解析&#xff1a;诗人角色的创意引导与实践 Prompt 模版作为一种结构化工具&#xff0c;旨在为特定角色——本例中的“诗人”——提供明确的指导和框架。这一模版详尽地描绘了诗人的职责、擅长的诗歌形式以及创作规则&#xff0c;使其能在自动化系统中更加精确地执…

咸鱼sign逆向分析与爬虫实现

目标&#xff1a;&#x1f41f;的搜索商品接口 这个站异步有点多&#xff0c;好在代码没什么混淆。加密的sign值我们可以通过搜索找到位置 sign值通过k赋值&#xff0c;k则是字符串拼接后传入i函数加密 除了开头的aff…&#xff0c;后面的都是明文没什么好说的&#xff0c;我…

学习记录:js算法(五十):二叉树的右视图

文章目录 二叉树的右视图我的思路网上思路 总结 二叉树的右视图 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 图一&#xff1a; 示例 1:如图一 输入: [1,2,3,null,5,null,4] …

uni-app #ifdef #ifndef #endif的使用和区别

1. uni-app #ifdef #ifndef #endif的使用和区别 条件编译是一种在编程中根据特定平台选择性编译代码的技术。如#ifdef和#endif根据APP-PLUS平台标识在微信小程序、支付宝小程序、百度小程序、头条小程序、QQ小程序以及H5应用中实现代码的平台特定执行。下面介绍了如何使用#ifde…

基于Java+SpringBoot3+vue3+uniapp点餐/外卖管理系统设计与实现(视频讲解)

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

微服务sentinel解析部署使用全流程

sentinel源码地址&#xff1a; 介绍 alibaba/Sentinel Wiki GitHub sentinel官方文档&#xff1a; https://sentinelguard.io/zh-cn/docs/introduction.html Sprong Cloud alibaba Sentinel文档【小例子】 : Sentinel alibaba/spring-cloud-alibaba Wiki GitHub 目录 1、…

wsl(1) --- win11环境配置

1. 开启WSL可选功能 打开设置&#xff0c;点击应用&#xff0c;点击可选功能&#xff0c;点击更多Windows功能&#xff0c;查看是否开启了【适用于Linux的Windows子系统】和【虚拟机平台】 2. 更新wsl 不执行这步&#xff0c;启动wsl镜像时会出现WslRegisterDistribution f…

带徒实训项目实战讲义分享:ApiFirst文档对比功能页面开发2

前一篇&#xff1a;带徒实训项目实战讲义分享&#xff1a;ApiFirst文档对比功能页面开发 亲爱的学员朋友们好&#xff0c;本小节跟小卷一起来学习用thymeleaf模板技术来渲染数据模型到表格中&#xff0c;通过本小节的学习&#xff0c;你会真正将thymeleaf模板技术应用到实处&a…

JavaScript 全攻略:从基础到精通

一、JavaScript 初印象 &#xff08;一&#xff09;起源与发展 JavaScript 的诞生源于对网页动态性的需求。1995 年&#xff0c;布兰登・艾奇仅用十天时间就设计出了这门语言&#xff0c;最初命名为 Mocha&#xff0c;后改为 LiveScript&#xff0c;最终定名为 JavaScript。它…

OLED显示屏中常见的3-spi和4-spi

显示屏中经常出现的IIC&#xff0c;3-spi和4-spi 其中&#xff0c;在用spi接口中经常用到的是4-spi&#xff0c;和IIC相比&#xff0c;spi有更高的传输速度。而IIC需要更少的引脚。下面是以SH1107驱动手册里的内容简单了解3-spi和4-spi区别 从两张图中可以看出&#xff0c;3…

Vue2(十三):路由

一、路由的简介 vue-rooter&#xff1a;是vue的一个插件库&#xff0c;专门用来实现SPA应用 1.对SPA应用的理解 1、单页 Web 应用&#xff08;single page web application&#xff0c;SPA&#xff09;。 2、整个应用只有一个完整的页面 index.html。 3、点击页面中的导航链…

Hutool工具包

下载jar包网址 hutool-all-5.3.2.jar下载及Maven、Gradle引入代码&#xff0c;pom文件及包内class -时代Java (nowjava.com) maven导入 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.2&l…

PHP后台+基于微信小程序外卖点餐系统毕业设计源代码作品和开题报告

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

Ansible学习之ansible-pull命令

想要知道ansible-pull是用来做什么的&#xff0c;就需要了解Ansible的工作模&#xff0c;Ansible的工作模式有两种&#xff1a; push模式 push推送&#xff0c;这是Ansible的默认模式&#xff0c;在主控机上编排好playbook文件&#xff0c;push到远程主机上来执行。pull模式 p…

一文搞懂CP-ABE,基于访问控制树的BSW方案原理分析与源码实现【基于C++、PBC库】

文章目录 一. 概述1.1 CP-ABE基础介绍1.2 访问控制树与BSW方案原理1.2.1 系统模型与角色1.2.2 主要算法1.2.3 访问结构与访问树1.2.4 数学基础 二. 具体算法流程2.1 Setup&#xff08;初始化&#xff09;2.2 KeyGen&#xff08;密钥生成&#xff09;2.3 Encrypt&#xff08;加密…

Typora---进度条(1)

本系列专门介绍关于typora中用到的小玩意。&#xff08;哈哈哈哈哈哈&#xff09; 本帖子讲述关于 进度条 的事情。 在typora中通过下面的语句可以显示出一个进度条&#xff1a; ![95% done](https://markdone.org/progress//95.png)通过更改上面语句中的数字可以展示不同的进…

local minima 的问题如何解决

&#x1f680; 在初始神经网络那一节&#xff08;链接如下&#xff1a;初识机器学习&#xff09;是遇到了两个问题&#xff0c;第一个是在求解函数未知参数数时会遇到local minima的问题&#xff0c;在哪里我们并没有过多解释&#xff0c;就是说一般遇不到并且很好解决&#xf…

合并两个有序数组(c语言)

1.//给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 //注意&#xff1a;最终&#xff0c;合并后数…