Vue3+TS封装axios

news2024/9/29 3:26:35

1.实现最基础的封装

将其封装为一个类,而不是一个函数的原因是因为类可以创建多个实例,适用范围更广,封装性更强一些。

index.ts 

// index.ts
import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
 
class ZJRequest {
  // axios 实例
 // 定义一个axion实例属性
  instance: AxiosInstance
// 利用构造函数要求传入使用 ZJRequest类时传入参数
  constructor(config: AxiosRequestConfig) {
 // 把axios实例赋给instance
    this.instance = axios.create(config)
  }
  request(config: AxiosRequestConfig) {
    return this.instance.request(config)
  }
}
 
export default ZJRequest

2.拦截器封装

首先我们封装一下拦截器,这个拦截器分为三种:

  • 类拦截器
  • 实例拦截器
  • 接口拦截器

接下来我们就分别实现这三个拦截器。

类拦截器

类拦截器比较容易实现,只需要在类中对axios.create()创建的实例调用interceptors下的两个拦截器即可,实例代码如下:

 // index.ts
constructor(config: AxiosRequestConfig) {
  this.instance = axios.create(config)
  
 // 添加所有的实例都有的拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // console.log('所有的实例都有的拦截器:请求拦截成功')
        if (this.showLoading) {
          this.loading = ElLoading.service({
            lock: true,
            text: '正在请求数据....',
            background: 'rgba(0,0,0,0.5)'
          })
        }

        return config
      },
      (err) => {
        // console.log('所有的实例都有的拦截器:请求拦截失败')
        return err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        // console.log('所有的实例都有的拦截器:响应拦截成功')
        // 将loading移除
        this.loading?.close()
        // 将loading移除
        // this.loading?.close()
        const data = res.data
        if (data.returnCode === '-1001') {
          console.log('请求失败,错误信息')
        } else {
          return data
        }
      },
      (err) => {
        console.log('所有的实例都有的拦截器:响应拦截失败')

        // 将loading移除
        this.loading?.close()

        if (err.response.status === 404) {
          console.log('404的错误')
        }
        return err
      }
    )
}

实例拦截器

实例拦截器是为了保证封装的灵活性,因为每一个实例中的拦截后处理的操作可能是不一样的,所以在定义实例时,允许我们传入拦截器。

首先我们定义一下interface,方便类型提示,代码如下:

 constructor(config: HYRequestConfig) {
    this.instance = axios.create(config)
    this.showLoading = config.showLoading ?? true
 // 实例拦截器
    this.interceptors = config.interceptors
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )
}

接口拦截

 request<T>(config: HYRequestConfig<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      // 1.单个请求对请求config的处理
      if (config.interceptors?.requestInterceptor) {
        config = config.interceptors.requestInterceptor(config)
      }

      // 2.判断是否需要显示loading
      if (config.showLoading === false) {
        this.showLoading = config.showLoading
      }

      this.instance
        .request<any, T>(config)
        .then((res) => {
          // 1.单个请求对数据的处理
          if (config.interceptors?.responseInterceptor) {
            res = config.interceptors.responseInterceptor(res)
          }
          // 2.将showLoading设置true, 这样不会影响下一个请求
          this.showLoading = DEAFULT_LOADING

          // 3.将结果resolve返回出去
          resolve(res)
        })
        .catch((err) => {
          // 将showLoading设置true, 这样不会影响下一个请求
          this.showLoading = DEAFULT_LOADING
          reject(err)
          return err
        })
    })
  }

  get<T>(config: HYRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: 'GET' })
  }

  post<T>(config: HYRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: 'POST' })
  }

  delete<T>(config: HYRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: 'DELETE' })
  }

  patch<T>(config: HYRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: 'PATCH' })
  }

3.完整的index.ts文件和type.ts

import axios from 'axios'
import type { AxiosInstance } from 'axios'
//导入自己定义的两个类型
import type { HYRequestInterceptors, HYRequestConfig } from './type'
import { ElLoading } from 'element-plus/lib/components/loading/index'
import { LoadingInstance } from 'element-plus/lib/components/loading/src/loading'

const DEAFULT_LOADING = true
class ZJRequest {
  instance: AxiosInstance
  interceptors?: HYRequestInterceptors
  showLoading: boolean
  loading?: LoadingInstance
  constructor(config: HYRequestConfig) {
    this.instance = axios.create(config)
    this.showLoading = config.showLoading ?? true
    this.interceptors = config.interceptors
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )

    // 添加所有的实例都有的拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // console.log('所有的实例都有的拦截器:请求拦截成功')
        if (this.showLoading) {
          this.loading = ElLoading.service({
            lock: true,
            text: '正在请求数据....',
            background: 'rgba(0,0,0,0.5)'
          })
        }

        return config
      },
      (err) => {
        // console.log('所有的实例都有的拦截器:请求拦截失败')
        return err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        // console.log('所有的实例都有的拦截器:响应拦截成功')
        // 将loading移除
        this.loading?.close()
        // 将loading移除
        // this.loading?.close()
        const data = res.data
        if (data.returnCode === '-1001') {
          console.log('请求失败,错误信息')
        } else {
          return data
        }
      },
      (err) => {
        console.log('所有的实例都有的拦截器:响应拦截失败')

        // 将loading移除
        this.loading?.close()

        if (err.response.status === 404) {
          console.log('404的错误')
        }
        return err
      }
    )
  }
  request<T>(config: HYRequestConfig<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      // 1.单个请求对请求config的处理
      if (config.interceptors?.requestInterceptor) {
        config = config.interceptors.requestInterceptor(config)
      }

      // 2.判断是否需要显示loading
      if (config.showLoading === false) {
        this.showLoading = config.showLoading
      }

      this.instance
        .request<any, T>(config)
        .then((res) => {
          // 1.单个请求对数据的处理
          if (config.interceptors?.responseInterceptor) {
            res = config.interceptors.responseInterceptor(res)
          }
          // 2.将showLoading设置true, 这样不会影响下一个请求
          this.showLoading = DEAFULT_LOADING

          // 3.将结果resolve返回出去
          resolve(res)
        })
        .catch((err) => {
          // 将showLoading设置true, 这样不会影响下一个请求
          this.showLoading = DEAFULT_LOADING
          reject(err)
          return err
        })
    })
  }

  get<T>(config: HYRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: 'GET' })
  }

  post<T>(config: HYRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: 'POST' })
  }

  delete<T>(config: HYRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: 'DELETE' })
  }

  patch<T>(config: HYRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: 'PATCH' })
  }
}

export default ZJRequest
import type { AxiosRequestConfig, AxiosResponse } from 'axios'

export interface HYRequestInterceptors<T = AxiosResponse> {
  requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestInterceptorCatch?: (error: any) => any
  responseInterceptor?: (res: T) => T
  responseInterceptorCatch?: (error: any) => any
}

export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
  interceptors?: HYRequestInterceptors<T>
  showLoading?: boolean
}

4.在index.js先导入ZJRequest

从config中导入相关的配置

new一个实例

//service统一的出口

import ZJRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
import localCache from '@/utils/cache'
// export default hyRequest =new HYRequest (){
// }
const zjRequest = new ZJRequest({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
  // 这是拦截器
  interceptors: {
    requestInterceptor: (config) => {
      // 携带token的拦截
      const token = localCache.getCache('token')
      if (token) {
        // 注意要加这个感叹号,不然会报错
        config.headers!.Authorization = `Bearer ${token}`
      }
      console.log(config)
      // console.log('请求成功的拦截')
      return config
    },
    requestInterceptorCatch: (err) => {
      // console.log('请求失败的拦截')
      return err
    },
    responseInterceptor: (res) => {
      // console.log('响应成功的拦截')
      return res
    },
    responseInterceptorCatch: (err) => {
      // console.log('响应失败的拦截')
      return err
    }
  }
})
export default zjRequest

5.测试是否发送请求成功

先定义返回的数据类型文件type.ts

export interface IDataType<T = any> {
  code: number
  data: T
}

 之后对应的请求代码中,可以加入IDataType规范返回的数据类型

export function requestUserInfoById(id: number) {
  return hyRequest.get<IDataType>({
    url: LoginAPI.LoginUserInfo + id,
    showLoading: false
  })
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/139286.html

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

相关文章

爬虫学习-selenium模块

与爬虫的关联可以便携的获取网站中动态加载的数据便携实现模拟登录基于游览器自动化的一个模块&#xff08;按键精灵脚本&#xff09;使用流程环境安装pip install selenium下载一个游览器的驱动程序&#xff1a;谷歌浏览器驱动安装 - 琳达的博客 - 博客园 (cnblogs.com)from s…

测试开发 | TestNG 与 Junit 对比,测试框架如何选择?

TestNG 和 Junit 作为两大流行的测试框架&#xff0c;有哪些区别&#xff1f;各有哪些优缺点&#xff1f;该如何选择呢&#xff1f;这里简要总结下&#xff1a;1. Junit 更适合隔离性比较强的单元测试&#xff1b;2. TestNG 是比 Junit 涵盖功能更全面的测试框架&#xff0c;具…

世界第一虚拟乐队举办了一场 AR 音乐会 #Gorillaz

“世界第一虚拟乐队” 是谁&#xff1f;23 年前&#xff0c;一支名为 Gorillaz 的乐队在英国埃塞克斯横空出世。和当时主流乐队形式不同的是&#xff0c;这支乐队以虚拟形象出现&#xff0c;凭借着过硬的音乐制作实力和别具一格的虚拟乐队形象&#xff0c;不久后就席卷了全球&a…

如何打造敏捷项目管理团队?【金曼说4】

曾经乔布斯说过他此生最骄傲的事不是创造了苹果&#xff0c;而且团队。由此也说明团队的重要性。一支优秀的团队能打造出无数优秀的产品和项目。无论是在商场还是战场上&#xff0c;快速反应和适应能力都至关重要&#xff0c;在技术和干扰性力量导致变革速度加快的时代更是如此…

HTML 常见面试题

一、HTML5&#xff08;超文本标记语言&#xff0c;第五次重大修改&#xff09;二、HTML5新特性①&#xff1a;新的语义标签 header footer nav aside article section②&#xff1a;新的表单控件 calendar date time email url search③&#xff1a;音频、视频&#xff08; aud…

地产2022价值启示录:房企必须闯过的“三重门”

回顾2022年&#xff0c;中国最大的经济变向之一&#xff0c;无疑就是地产增量时代的落幕。过去一整年&#xff0c;地产行业在“冷热交替”中前行。上半年&#xff0c;疫情、交付延期、停贷潮等阴霾萦绕在众多房企头顶上&#xff0c;市场需求疲软之下业绩下滑&#xff0c;难以看…

《MySQL系列-InnoDB引擎10》InnoDB关键特性-异步IO

InnoDB 关键特性 InnoDB存储引擎的关键特性包括&#xff1a; Insert Buffer (插入缓冲)Double Write (两次写)Adaptive Hash Index (自适应哈希索引)Async IO (异步IO)Flush Neighbor Page (刷新领接页) 这些特性为InnoDB存储引擎带来了更好的性能以及更高的可靠性。 异步IO 为…

在外打工好久不回老家,用python为家里贴上新年春联

每逢春节&#xff0c;无论城市还是农村&#xff0c; 家家户户都要挑漂亮的红春联贴于门上&#xff0c;辞旧迎新&#xff0c;增加喜庆的节日气氛。 唠叨神话 据说这一习俗起于宋代&#xff0c;在明代开始盛行&#xff0c; 到了清代&#xff0c;春联的思想性和艺术性都有了很…

SpringBoot @ConfigurationProperties使用详解

SpringBoot ConfigurationProperties使用详解 目录SpringBoot ConfigurationProperties使用详解1.1 简述1.2 场景一1.3 场景二1.4 场景三1.5 聊聊EnableConfigurationProperties1.1 简述 在Spring Boot中注解ConfigurationProperties有三种使用场景&#xff0c;而通常情况下我…

51单片机学习笔记_6 IO通信:电脑与单片机之间的通信

通信 单片机还可以通过IO口实现多种通信。 串行通信&#xff1a;一条数据线&#xff0c;一次发1bit&#xff0c;发很久。 并行通信&#xff1a;多条数据线&#xff0c;同时发送&#xff0c;发的速度快多了但是费用高、接收困难、抗干扰性差。 异步通信&#xff1a;发送和接…

PMP、ACP、软考证书,当前哪些值得一考?

看自己的偏向吧&#xff0c;要说考的话&#xff0c;是都值得考的。ACP和PMP都是美国PMI发起的考试&#xff0c;软考是国内的考试。PMP是项目管理证书&#xff0c;学习的内容是项目管理&#xff0c;包含大约一半的敏捷项目管理的内容&#xff0c;ACP的内容都是敏捷项目管理&…

操作系统第三次实验-动态分区存储管理(python代码实现)

一、实验目的&#xff1a; 目的&#xff1a;熟悉并掌握动态分区分配的各种算法&#xff0c;熟悉并掌握动态分区中分区回收的各种情况&#xff0c;并能够实现分区合并。 任务&#xff1a;用高级语言模拟实现动态分区存储管理。 二、实验内容&#xff1a; 1、实验内容 分区分配算…

Qt 编译出的程序无法在其他电脑运行

明确构建套件&#xff08;Kit&#xff09; Kit 包含了构建程序所需的全部工具&#xff0c;例如编译器&#xff0c;可以从Qt Creator 左下角查看Kit。 我这里使用的Kit是Desktop Qt 5.12.6 MinGW 64-bit 打开 Kit 版本对应的 Qt 命令行工具 我这里需要打开Qt 5.12.6 (MinGW 7.3…

php反序列化字符逃逸

php反序列化字符逃逸 php反序列化字符逃逸的原理 当开发者使用先将对象序列化&#xff0c;然后将对象中的字符进行过滤&#xff0c;最后再进行反序列化。这个时候就有可能会产生PHP反序列化字符逃逸的漏洞。 php反序列化字符逃逸分类 过滤后字符变多 过滤后字符变少 过滤后字…

Alma Linux和Rocky Linux,你会选择用哪个?

AlmaLinux和Rocky Linux是两个基于 Red Hat Enterprise Linux (RHEL) 发行版的免费开源操作系统&#xff0c;两者都旨在由社区驱动、透明且稳定&#xff0c;但两者之间存在一些关键差异。 Rocky Linux Rocky Linux 是一个基于 Red Hat Enterprise Linux (RHEL) 发行版的免费开…

Android 音视频学习之《MediaCodec》

一、介绍以及编解码流程 MediaCodec 类可用于访问低级媒体编解码器&#xff0c;即编码器/解码器组件。它是 Android 低级多媒体支持基础结构的一部分&#xff08;通常与MediaExtractor、MediaSync、MediaMuxer、MediaCrypto、 MediaDrm、Image、Surface和一起使用AudioTrack。…

060-MySQL数据库综合应用(实现登录及注册功能源代码)

【上一讲】059-MySQL数据库综合应用(实现登录及注册功能)_CSDN专家-赖老师(软件之家)的博客-CSDN博客 本文章讲解JAVA数据库技术与MySQL数据库结合使用,利用DAO技术对数据库操作进行封装,达到高内聚低耦合,具体技术如下: 1.综合利用JAVA数据库技术,掌握Connection,St…

操作系统第四次实验-基本分页存储管理(python代码实现)

一、实验目的&#xff1a; 目的&#xff1a;熟悉并掌握基本分页存储管理的思想及其实现方法&#xff0c;熟悉并掌握基本分页存储管理的分配和回收方式。 任务&#xff1a;模拟实现基本分页存储管理方式下内存空间的分配和回收。 二、实验内容&#xff1a; 1、实验内容 内存空间…

一道有意思的图论题

今天写这道题的过程就一直在摆&#xff0c;主要是写不太出来&#xff0c;之前想到动态规划去了&#xff0c;然后又开始深搜&#xff0c;在出口那块放动态规划 题&#xff1a; D. Ela and the Wiring Wizard 点我 但是cf让我明白了一个道理&#xff0c;任何一道我写不出来的题代…

点菜方案数

题目描述 不过uim的口袋里只剩 M元(M < 10000)&#xff0c;来到了一家低端餐馆前。 餐馆虽低端&#xff0c;但是菜品种类不少&#xff0c;有 N 种(N < 100)&#xff0c;第i种卖元(ai < 1000)。由于是很低端的餐馆所以每种菜只有一份。 uim奉行“不把钱吃光不罢休”&a…