TypeScript 封装 Axios 1.7.7

随着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.mfbz.cn/a/885878.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Golang | Leetcode Golang题解之第441题排列硬币

题目&#xff1a; 题解&#xff1a; func arrangeCoins(n int) int {return sort.Search(n, func(k int) bool { k; return k*(k1) > 2*n }) }

【Unity服务】如何使用Unity Version Control

Unity上的线上服务有很多&#xff0c;我们接触到的第一个一般就是Version Control&#xff0c;用于对项目资源的版本管理。 本文介绍如何为项目添加Version Control&#xff0c;并如何使用&#xff0c;以及如何将项目与Version Control断开链接。 其实如果仅仅是对项目资源进…

09_OpenCV彩色图片直方图

import cv2 import numpy as np import matplotlib.pyplot as plt %matplotlib inlineimg cv2.imread(computer.jpeg, 1) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img) plt.show()plot绘制直方图 plt.hist(img.ravel(), 256) #ravel() 二维降一维 256灰度级…

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

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

C++面向对象基础

目录 一.函数 1.内联函数 2.函数重载 3.哑元函数 二.类和对象 2.1 类的定义 2.2 创建对象 三. 封装&#xff08;重点&#xff09; 四. 构造函数 constructor&#xff08;重点&#xff09; 4.1 基础使用 4.2 构造初始化列表 4.3 构造函数的调用方式&#xff08;掌握…

解决方法:PDF文件打开之后不能打印?

打开PDF文件之后&#xff0c;发现文件不能打印&#xff1f;这是什么原因&#xff1f;首先我们需要先查看一下自己的打印机是否能够正常运行&#xff0c;如果打印机是正常的&#xff0c;我们再查看一下&#xff0c;文件中的打印功能按钮是否是灰色的状态。 如果PDF中的大多数功…

秋招内推--招联金融2025

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

数据结构-LRU缓存(C语言实现)

遇到困难&#xff0c;不必慌张&#xff0c;正是成长的时候&#xff0c;耐心一点&#xff01; 目录 前言一、题目介绍二、实现过程2.1 实现原理2.2 实现思路2.2.1 双向链表2.2.2 散列表 2.3 代码实现2.3.1 结构定义2.3.2 双向链表操作实现2.3.3 实现散列表的操作2.3.4 内存释放代…

SigmaStudio控件Cross Mixer\Signal Merger算法效果分析

衰减与叠加混音算法验证分析一 CH2:输入源为-20dB正弦波1khz CH1叠加混音&#xff1a;参考混音算法https://blog.csdn.net/weixin_48408892/article/details/129878036?spm1001.2014.3001.5502 Ch0衰减混音&#xff1a;外部多个输入源做混音时&#xff0c;建议参考该算法控件&…

在VMware虚拟机上部署polardb

免密登录到我们的虚拟机之后&#xff0c;要在虚拟机上部署polardb数据库&#xff0c;首先第一步要先克隆源码&#xff1a; 为了进SSH协议进行传输源码需要先进行下面的步骤&#xff1a; 将宿主机上的私钥文件复制到虚拟机上 scp "C:\Users\waitw\.ssh\id_rsa" ann…

Azkaban:大数据任务调度与编排工具的安装与使用

在当今大数据时代&#xff0c;数据处理和分析任务变得越来越复杂。一个完整的大数据分析系统通常由大量任务单元组成&#xff0c;如 shell 脚本程序、mapreduce 程序、hive 脚本、spark 程序等。这些任务单元之间存在时间先后及前后依赖关系&#xff0c;为了高效地组织和执行这…

Leetcode 每日一题:Crack The Safe

写在前面&#xff1a; 学期真的忙起来了&#xff0c;我的两个社团也在上一周终于完成了大部分招新活动。虽然后面有即将到来的期中考试和求职&#xff0c;但希望能有时间将帖子的频率提上去吧&#xff08;真的尽量因为从做题思考到写博客讲解思路需要大量的时间&#xff0c;在…

当人工智能拥抱餐饮业,传统与创新的交融

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 今天我们要聊一个充满烟火气的行业&#x…

Threejs绘制圆锥体

上一章节实现了胶囊体的绘制&#xff0c;这节来绘制圆锥体&#xff0c;圆锥体就是三角形旋转获得的&#xff0c;如上文一样&#xff0c;先要创建出基础的组件&#xff0c;包括场景&#xff0c;相机&#xff0c;灯光&#xff0c;渲染器。代码如下&#xff1a; initScene() {this…

信息安全工程师(22)密码学网络安全应用

前言 密码学在网络安全中的应用极为广泛且深入&#xff0c;它通过多种技术手段确保数据的机密性、完整性和真实性。 一、数据加密 对称加密&#xff1a; 定义&#xff1a;使用相同的密钥进行加密和解密的过程。特点&#xff1a;加密和解密速度快&#xff0c;适用于大数据量的加…

网站集群批量管理-密钥认证与Ansible模块

一、集群批量管理-密钥认证 1、概述 管理更加轻松&#xff1a;两个节点,通过密钥形式进行访问,不需要输入密码,仅支持单向. 服务要求(应用场景)&#xff1a; 一些服务在使用前要求我们做秘钥认证.手动写批量管理脚本. 名字: 密钥认证,免密码登录,双机互信. 2、原理 税钥对…

websocket集群部署遇到的一些事

最近刚好有个场景&#xff0c;业务处理一份报告需要关注实时处理的进度。 本来打算使用前端轮训方式&#xff0c;但是考虑到这样效率比较低&#xff0c;也无法精确知道处理进度&#xff0c;就想到用websocket和前端实时交互&#xff0c;进度有更新就通知前端&#xff0c;避免了…

视频集成与融合项目中需要视频编码,但是分辨率不兼容怎么办?

在众多视频整合项目中&#xff0c;一个显著的趋势是融合多元化的视频资源&#xff0c;以实现统一监管与灵活调度。这一需求促使项目团队不断探索新的集成方案&#xff0c;确保不同来源的视频流能够无缝对接&#xff0c;共同服务于统一的调看与管理平台&#xff0c;进而提升整体…

MobaXterm基本使用 -- 服务器状态、批量操作、显示/切换中文字体、修复zsh按键失灵

监控服务器资源 参考网址&#xff1a;https://www.cnblogs.com/144823836yj/p/12126314.html 显示效果 MobaXterm提供有这项功能&#xff0c;在会话窗口底部&#xff0c;显示服务器资源使用情况 如内存、CPU、网速、磁盘使用等&#xff1a; &#xff08;完整窗口&#xff0…

GAMES101(17~18节,物理材质模型)

材质 BRDF 材质&#xff1a;决定了光线与物体不同的作用方式 BRDF定义了物体材质,包含漫反射和镜面部分 BSDF &#xff08;scattering散射&#xff09; BRDF&#xff08;reflect反射&#xff09; BTDF 光线打击到物体上会向四面八方散射 反射 光线打击到物体上反射出去…