Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Axios的封装思想及实践(TS版本)

Axios的封装思想及实践(TS版本)

作者头像
玖柒的小窝
修改于 2021-10-26 07:32:38
修改于 2021-10-26 07:32:38
2.7K00
代码可运行
举报
文章被收录于专栏:各类技术文章~各类技术文章~
运行总次数:0
代码可运行

源于coderWhy教学视频思想,对axios做一个简单的小结,再次感谢coderwhy大神

Axios官网(中文):Axios (axios-http.com)

基本安装

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//npm方式
npm install axios
//yarn方式
yarn add axios
复制代码

基本使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
axios(config)
axios.request(config)
axios.get(config)
axios.post(config)
复制代码

缺点是耦合度太高,相同配置需多次重复,且不灵活

封装思想

  • 直接使用axios,依赖性太强,如果今后更换网络请求库会很麻烦
  • 一些公共的请求功能,每次请求都需要重写配置
  • aixos进行加一层封装,将axios封装为自定义的request,将来直接使用request来发送网络请求就行,日后想要更换网络请求库,可以直接修改request层,将一些公共的功能封装在request层,如网络请求头添加Authorization(即token),加载loading效果等等,拦截器可以灵活封装

使用Typescript进行封装的一些前置知识梳理

  1. axios(config)config的类型为AxiosRequestConfig,具体见官网:请求配置 | Axios 中文文档 (axios-http.cn) 常用的有几个:url,method,baseUrl,data,timeout等 默认配置可以进行升级改造,新建一个接口实现AxiosRequestConfig,在其中添加一些新的配置
  2. AxiosResponse---axios默认的返回值类型,接收泛型T默认为any,代表的是实际接收到的返回数据类型,一般会将T设置为IDataType。 //一般情况下我们只使用data export interface AxiosResponse<T = any> { data: T; status: number; statusText: string; headers: any; config: AxiosRequestConfig; request?: any; } //一般在使用中,我们会将返回数据类型定义为如下形式 export interface IDataType<T = any> { status: string msg: string data: T } 复制代码 日常使用中,我们不会使用AxiosResponse作为封装后的返回值数据类型,会提取其中的data,可以通过在响应成功拦截器中返回result.data来实现(后面会详细介绍),而data的类型即为IDataType
  3. 封装统一使用原生实例的request方法来进行 //T默认是any类型,返回值默认是AxiosResponse<T> request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>; 复制代码 封装后实现的效果如下: //T即为IDataType类型,返回的是一个Promise<T> xxRequest.get<T>(config: xxRequestConfig<T>): Promise<T> 复制代码

一、封装一(去耦合)

  1. 创建自定义网络请求类JJRequest,将axios实例包装在内 //service/request/request.ts class JJRequest { instance: AxiosInstance constructor(config: AxiosRequestConfig) { this.instance = axios.create(config) } //返回的Promise中结果类型为AxiosResponse<any> request(config: AxiosRequestConfig): Promise<AxiosResponse> { return new Promise<AxiosResponse>((resolve, reject) => { this.instance .request(config) .then((res) => { resolve(res) }) .catch((err) => { reject(err) }) }) } } 复制代码
  2. 创建实例(仅配置基本的baseURLtimeout,属于实例级别配置) //service/index.ts //使用环境配置 const jjRequest = new JJRequest({ baseURL: process.env.VUE_APP_BASE_URL, timeout: process.env.VUE_APP_TIME_OUT }) 复制代码
  3. 具体使用 //main.ts jjRequest .request({ url: '/xxx' }) .then((res) => { console.log(res) }) 复制代码

查看结果:可以看出结果为AxiosResponse<any>类型

二、封装二(添加全局级别拦截)

原生的拦截器位于axiosInstance实例中,使用方法是(来源官网:拦截器 | Axios 中文文档 (axios-http.cn)

注意:响应成功和响应失败的判别标准,以状态码2xx为界限,超出的响应失败

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
  });
复制代码

全局拦截在JJRequest的构造函数中实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//service/request/request.ts
//省略前后部分代码
//....
constructor(config: AxiosRequestConfig) {
  this.instance = axios.create(config)
  
  //全局请求拦截
  this.instance.interceptors.request.use(
      (config) => {
        console.log(config)
        return config
      },
      (error) => {
        console.log('全局请求失败拦截', error)
      }
    )
  //全局响应拦截
    this.instance.interceptors.response.use(
      (res) => {
        //res为AxiosResponse类型,含有config\data\headers\request\status\statusText属性
        console.log(res)
        //改造返回的数据类型,即将AxiosResponse的data返回
        return res.data
      },
      (error) => {
        console.log('全局响应失败拦截')
        console.log(error.request)//
        console.log(error.response)
        return error
      }
    )
  
  //加入泛型限定,返回数据类型为T,
  request<T>(config: AxiosRequestConfig<T>): Promise<T> {
    return new Promise<T>((resolve, reject) => {
      this.instance
        .request<any, T>(config)
        .then((res) => {
          resolve(res)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }
}
复制代码

实际使用时如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//main.ts==>返回的数据类型限定为IDataType
jjRequest
  .request<IDataType>({
    url: '/xxx'
  })
  .then((res) => {
    console.log(res)
  })
  .catch((err) => {
    console.log('=====', err)
  })
复制代码

同封装一的接口在main.ts中运行后效果如下,只剩下AxiosResponse中的data,此处为自定义的IDataType类型,暂时还未明确加入泛型,后面会加入

演示响应失败的拦截:(将后端接口中的/xxx改为了/xxxx,则前端访问/xxx将出现响应失败404

三、封装三(自定义实例级别的拦截器,添加token)

需实现的效果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//service/index.ts
const jjRequest = new JJRequest({
  baseURL: process.env.VUE_APP_BASE_URL,
  timeout: process.env.VUE_APP_TIME_OUT,
  //实例级别的拦截器,在创建axios实例的时候携带拦截器
  interceptors:{
    requestInterceptor: ...
    requestInterceptorCatch: ...
    responseInterceptor: ...
    responseInterceptorCatch: ...
  }
})
复制代码

因为原生的AxiosRequestConfig中没有拦截器配置这个属性,因此需要自定义改造,一是自定义拦截器接口,二是自定义请求配置接口

  1. 自定义拦截器接口(共四个拦截器,四个函数) interface IJJRequestInterceptors<T = AxiosResponse> { //请求成功 requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig //请求失败 requestInterceptorCatch?: (error: any) => any //响应成功 responseInterceptor?: (res: T) => T //响应失败 responseInterceptorCatch?: (error: any) => any } 复制代码
  2. 自定义请求配置接口,可选属性,可配可不配 interface IJJRequestConfig<T = AxiosResponse> extends AxiosRequestConfig { interceptors?: IJJRequestInterceptors<T> } 复制代码
  3. 改造网络请求类 class JJRequest { instance: AxiosInstance //该属性从实例中获取 interceptors?: IJJRequestInterceptor constructor(config: IJJRequestConfig) { this.instance = axios.create(config) //从实例配置config中获取拦截器配置 this.interceptors = config.interceptors //全局请求拦截 this.instance.interceptors.request.use(..., ...) //全局响应拦截 this.instance.interceptors.response.use(..., ...) //实例级别拦截 this.instance.interceptors.request.use( this.interceptors?.requestInterceptor, this.interceptors?.requestInterceptorCatch ) this.instance.interceptors.response.use( this.interceptors?.responseInterceptor, this.interceptors?.responseInterceptorCatch ) } } 复制代码
  4. 创建实例 const jjRequest = new JJRequest({ baseURL: process.env.VUE_APP_BASE_URL, timeout: process.env.VUE_APP_TIME_OUT, interceptors: { requestInterceptor: (config) => { //此处token在开发中可从localStorage中获取,token一般从服务器获取存在vuex中,然后转存到localStorage中,自己封装关于localStorage的方法,此处用一个常量代替 //const token = localCache.getCache('token') const token = 'this ia a token' if (token) { config.headers.Authorization = `Bearer ${token}` } return config } } }) 复制代码

结果展示

四、封装四(单个请求调用级别的拦截)

实现调用级别的拦截,需要在request方法中做文章,将其参数类型也由AxiosRequestConfig升级为IJJRequestConfig,实现的思路是直接调用该方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//service/request/request.ts
//...
request<T>(config: IJJRequestConfig<T>): Promise<T> {
    return new Promise<T>((resolve, reject) => {
      //请求拦截设置位置
      if (config.interceptors?.requestInterceptor) {
        config = config.interceptors.requestInterceptor(config)
      }

      this.instance
        .request<any, T>(config)
        .then((res) => {
          //响应拦截设置位置
          if (config.interceptors?.responseInterceptor) {
            res = config.interceptors.responseInterceptor(res)
          }
          resolve(res)
        })
        .catch((err) => {
          console.log('=====', err)
          reject(err)
        })
    })
  }
复制代码

调用时如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
jjRequest
  .request<IDataType>({
    url: '/xxx',
  //单个请求调用级别单独设置拦截器
    interceptors: {
      //直接返回IDataType类型结果中的data属性项
      responseInterceptor: (res) => res.data
    }
  })
  .then((res) => {
    console.log(res)
  })
  .catch((err) => {
    console.log('=====', err)
  })
复制代码

结果如下

五、封装五(封装get、post等,方便调用)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 //service/request/request.ts
 //....
 get<T = any>(config: IJJRequestConfig<T>): Promise<T> {
     return this.request<T>({
       ...config,
       method: 'GET'
     })
   }
 ​
   post<T = any>(config: IJJDRequestConfig<T>): Promise<T> {
     return this.request<T>({
       ...config,
       method: 'POST'
     })
   }
   //其余patch、delete等参照一样的,实际调用时可直接使用jjRequest.get<IDataType>(config)来请求数据
复制代码

axios的封装划分了三层

  • 全局层
  • 实例层
  • 单个请求层

将来可以根据实际情况做相应的封装,主要考虑的是将封装放在哪一层来做,本文主要是写一写封装的思想 例如loading加载效果,可以在全局来做,也可以在实例层来做,也可以在单个请求处来做,看具体需求!此处就不在做具体的封装,仅做抛砖引玉的作用!

补充:拦截的执行顺序

对于axios的封装还有很多,比如关于重复请求的封装、参数序列化等,按需进行即可。ps:主要是我还不会,哈哈。。

来自一个业余程序爱好者小弟的小结,不足之处,请各位大佬指正!

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
vue3 +ts 如何安装封装axios
先在 src 下创建一个 utils文件夹,并添加一个 request.ts 文件
肥晨
2023/04/04
2.4K0
教你如何让 Axios 更加灵活可复用
这里将其封装为一个类,而不是一个函数的原因是因为类可以创建多个实例,适用范围更广,封装性更强一些。
前端老道
2022/08/30
1.1K0
HarmonyOS NEXT实战:接入和使用axios
https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Faxios
中雨
2025/06/27
1090
基于Axios二次封装请求库,带你重构面试亮点
在我以往的面试中,听到候选人最多的就是项目中二次封装axios,但是当真正深入挖掘,往往得不到有用的信息。 那么面试官是想听到什么样的亮点呢?这篇文章我们重点分析一下,并且也可以封装自己的axios请求库。
linwu
2023/08/14
4560
基于TypeScript封装Axios笔记(六)
我们希望能对请求的发送和响应做拦截,也就是在发送请求之前和接收到响应之后做一些额外逻辑。
用户7572539
2020/08/26
1.7K0
vue3 + vite 进行axios请求封装及接口API的统一管理
这篇文章跟vite关系不大,下篇写环境变量配置的时候就是vite相关了,今天这里主要讲一下在vue3中axios的实战用法以及Api的统一管理,手把手教学望各位在这里能碰擦出灵感的火花,放飞五彩的思绪。
inline705
2021/12/09
19.2K0
vue3 + vite 进行axios请求封装及接口API的统一管理
基于TypeScript封装Axios笔记(五)
为了用户更加方便地使用 axios 发送请求,我们可以为所有支持请求方法扩展一些接口:
用户7572539
2020/08/26
3.7K0
axios 如何设计拦截器
最近在做axios的二次封装,在配置拦截器时。发现实际的调用流程与预想的不太一致。所以去看了看axios拦截器部分的源码,大概了解拦截器的实现。 一下是对拦截器实现的一些理解。
copy_left
2022/03/23
7700
【Vue3+TypeScript】CRM系统项目搭建之 — Axiox 网络请求封装
使用 vue 开发时,频繁使用到了 axios 这个网络请求库,这里对其做一个发起请求时携带参数方式的小结。
HelloWorldZ
2024/03/20
3350
【Vue3+TypeScript】CRM系统项目搭建之 — Axiox 网络请求封装
一个基于vite构建的vue3+pinia+ts+elementUI plus的初始化开箱即用的项目模版
Vite 需要 Node.js 版本 >= 12.0.0。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
用户6297767
2023/11/21
1.1K0
一个基于vite构建的vue3+pinia+ts+elementUI plus的初始化开箱即用的项目模版
一文读懂Axios核心源码思想
我们以特性作为入口,解答上述问题的同时一起感受下 Axios 源码极简封装的艺术。
@超人
2021/11/17
9710
使用Typescript实现轻量级Axios
文章首发于@careteen/axios(存放了下文涉及所有代码),转载注明来源即可。
Careteen
2022/02/14
3.2K0
使用Typescript实现轻量级Axios
axios请求二次封装,兼容typescript
适合初学者配置使用,只封装了get和post其他类似patch、put和axios.all()的方法得自己动手了,如果遇到项目有多个baseURL的这套封装就显得很不灵活,但一般是不会遇到的,这套简单的封装总的来说够用了,且非常实用。 新建https.ts复制下面代码进去引用即可,如果是js版本的把url:any, param:any后面的:any去掉。 import axios from 'axios' import qs from 'qs' axios.defaults.timeout = 5000;
骤雨重山
2022/01/17
8870
axios封装
訾博ZiBo
2025/01/06
1720
Axios入门与源码解析
(1) 需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一样, 如何处理
鱼找水需要时间
2023/02/16
3.2K0
Axios入门与源码解析
axios 二次封装-状态处理拦截器
上篇[axios 二次封装-拦截器队列, 这篇是基于拦截器队列实现的状态处理拦截器, 某些情况下我们需要针对不同的响应状态码,执行不同的处理函数。例如:
copy_left
2022/05/13
9370
Vue学习-axios
以下的axios网络请求的代码都在Vue项目src文件夹下的main.js中完成。
花猪
2022/02/17
9750
Vue学习-axios
HarmonyOS 开发实践 —— 基于@ohos/axios的网络请求能力
Axios 是一个基于promise的网络请求库,可以运行node.js和浏览器中。基于Axios原库v1.3.4GitHub版本进行适配,使其可以运行在OpenHarmony并沿用其现有用法和特性。
小帅聊鸿蒙
2024/12/03
6700
HarmonyOS 开发实践 —— 基于@ohos/axios的网络请求能力
基于TypeScript封装Axios笔记(九)
有些时候我们会发一些跨域请求,比如 http://domain-a.com 站点发送一个 http://api.domain-b.com/get 的请求,默认情况下,浏览器会根据同源策略限制这种跨域请求,但是可以通过 CORS 技术解决跨域问题。
用户7572539
2020/08/26
2.5K0
axios详解以及完整封装方法
Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
HelloWorldZ
2024/03/20
12.8K0
相关推荐
vue3 +ts 如何安装封装axios
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验