基于Axios二次封装请求库,带你重构面试亮点(二)

简介: 基于Axios二次封装请求库,带你重构面试亮点

支持区分env


这样配置有个好处。有时候我们新增的接口想走本地mock,比如后端还未实现,已有的接口走线上数据,这样以配置,就简单明了多了

baseMap: {
      prod: 'https://wwww.baidu.com',
      test: 'https://wwww.baidu.com',
      local: 'http://127.0.0.1:4320',
      baseURL: 'https://localhost:8080'
    },
export default {
  getBaseInfo: {
    method: 'get',
    url: '/base/get',
    env:'local'
  },
  getBaseRestInfo: {
    method: 'get',
    url: '/base/get/:id/kill/:test',
    env:'test'
  }
}


支持restful风格

export default {
  getBaseInfo: {
    method: 'get',
    url: '/base/get',
    env:'local'
  },
  getBaseRestInfo: {
    method: 'get',
    url: '/base/get/:id/qs/:test',
    env:'test'
  }
}


实现:

  /**
   * 替换restful请求中的url
   */
  restful(url: string, rest: Rest): string {
    /**
     * [xyz]一个字符集合。匹配方括号中的任意字符
     * 比如正则表达式是[abcd]==>匹配brisket"中的‘b’
     */
    const regex = /\:[^/]*/g
    /**
     * 一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。参考下面的指定一个函数作为参数。
     * 另外要注意的是,如果第一个参数是正则表达式,并且其为全局匹配模式,那么这个方法将被多次调用,每次匹配都会被调用。
     * 匹配模式是这样的\:[^/]* 为一个整体 全局g下多次匹配 也就是多次调用fn
     * [^/]匹配得到的是一个字符 只要匹配的url出现的一个字符在 [^/]中出现就匹配成功 但是是单个的 所以要多次匹配
     */
    return url.replace(regex, p => {
      console.log(p)
      /**
       * :id ===>返回id
       */
      const key = p.slice(1)
      if (rest[key]) {
        return rest[key]
      }
      return p
    })
  }


支持取消请求


v0.22.0 开始,Axios 支持以 fetch API 方式—— AbortController 取消请求:

// 1. 支持取消请求
const cancelMap: { [key: string]: any } = {}
Apis.reqMiddleware.push({
  onFulfilled: (config) => {
    const source = axios.CancelToken.source()
    config.cancelToken = source.token
    cancelMap[config.url!] = source
    return config
  }
})
createInstance.cancel = function(url: string) {
  if (cancelMap[url]) {
    cancelMap[url].cancel('Request was cancelled')
    delete cancelMap[url]
  }
}


支持重新请求


function createInstance(
  serverMap: ServerMap,
  apiMap: ApisMap,
  common?: AxiosRequestConfig
): ApisInstance {
  Apis.resMiddleware.push({
    onFulfilled: void 0,
    onRejected: function axiosRetryInterceptor(err) {
      const config = err.config
      /**
       * 如果没有retry配置那么就不走这个拦截器
       * 因为发生错误,我们还在这个拦截器中 request2 interceptor --> request1 interceptor-->dispatchRequest--> response1 interceptor--> response2 interceptor
       * 这时候在拦截器中重新发起请求把得到的响应结果发给最后的Promise
       * 最后的Promise注册中我们成功和失败的业务
       * 这样可以避免:其他的那个几十个.vue页面的 this.$axios的get 和post 的方法根本就不需要去修改它们的代码。
       */
      if (!config || !config.retry) return Promise.reject(err)
      /**
       * 已经尝试retry的次数
       */
      config.__retryCount = config.__retryCount || 0
      if (config.__retryCount >= config.retry) {
        return Promise.reject(err)
      }
      config.__retryCount += 1
      /**
       * 等待多少秒后才进行retry
       */
      const backoff = new Promise(function(resolve) {
        setTimeout(function() {
          resolve()
        }, config.retryDelay || 1)
      })
      return backoff.then(function() {
        /**
         * 返回结果
         * 是个Promise对象
         * 不reject 返回的数据被成功的回调拿到
         */
        return axios(config)
      })
    }
  })
  const apis = new Apis(serverMap, apiMap, common)
  /**
   * new过后清空以前的拦截器队列
   * 因为new完一个实例过后,拦截器信息可以作废
   * 所以要确保你实例化之前先注册拦截器
   */
  Apis.reqMiddleware = []
  Apis.resMiddleware = []
  return apis.instance
}


支持缓存


// 3. 支持接口缓存
const cacheMap: { [key: string]: any } = {}
Apis.resMiddleware.push({
  onFulfilled: (response) => {
    cacheMap[response.config.url!] = response
    return response
  }
})
Apis.reqMiddleware.push({
  onFulfilled: (config) => {
    if (cacheMap[config.url!]) {
      throw new axios.Cancel('Request was cached')
    }
    return config
  }
})


支持限流


// 2. 支持接口限流
const LIMIT = 5 // 例如,5个请求每秒
const INTERVAL = 1000 // 1秒
let tokens = LIMIT
setInterval(() => { tokens = LIMIT }, INTERVAL)
Apis.reqMiddleware.push({
  onFulfilled: (config) => {
    if (tokens > 0) {
      tokens--
      return config
    } else {
      throw new Error('Rate limit exceeded')
    }
  }
})

总结


上述的apis是我实际项目中封装的,当然文章给的大部分是伪代码,但是思路是对的,大家可以按照这个思路封装自己项目中的请求库,然后发布成npm包


目录
相关文章
|
1月前
|
资源调度 JavaScript
|
1月前
|
缓存 JavaScript 搜索推荐
|
16天前
|
JavaScript 前端开发 Java
SpringBoot项目的html页面使用axios进行get post请求
SpringBoot项目的html页面使用axios进行get post请求
40 2
|
1月前
|
Python
axios的get请求传入数组参数
【10月更文挑战第11天】 当使用 `axios` 发送包含数组参数的 GET 请求时,默认的序列化方式可能与后端(如 Django)不兼容,导致无法正确获取数组参数。解决方案是通过 `paramsSerializer` 指定自定义序列化函数,或使用 `qs` 库来格式化数组参数,确保前后端一致。示例代码展示了如何使用 `qs` 库设置 `arrayFormat` 为 `"repeat"`,以符合 Django 的解析要求。
25 2
|
1月前
|
JSON JavaScript 前端开发
axios的post请求,数据为什么要用qs处理?什么时候不用?
axios的post请求,数据为什么要用qs处理?什么时候不用?
|
30天前
|
前端开发 JavaScript UED
axios取消请求CancelToken的原理解析及用法示例
axios取消请求CancelToken的原理解析及用法示例
86 0
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
8天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
9天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
33 4

热门文章

最新文章

  • 1
    若依修改,若依如何发送请求---王清江07,axios的请求在request.js文件中,若依发送GET请求,必须用param
    119
  • 2
    axios发送post请求,如何接受和返回一个axios的字段,解决bug的方法,困难的事情先从简单做起,先从发送一个axios的post请求做起,解决方法查别人的资料,查看F12看network就行
    42
  • 3
    文本,前后端数据交互,简单请求,如何去给data数据赋值,在mounted()里赋值,利用axios发送的请求,res就是数据集,就是后端的数据,this.users = res.data.data
    45
  • 4
    Request failed with status code 400,使用axios.post要发送参数,认真比对原项目,看看有没有忘记什么?
    84
  • 5
    vue3 在 watchEffect 里中断未完成的 axios 请求(只保留最后一次请求的方法---连续点击查询按钮的优化)
    117
  • 6
    前后端数据交互.js文件的axios的写法,想要往后端发送数据,页面注入API,await的意思是同步等待服务器数据,并返回,axios注入在其他页面,其他页面调用的时候,同步作用
    42
  • 7
    前后端数据交互,API风格组合式API和选项式API,setup是一个标识,组合式编写的意思,使定义count.value的值自增的写法,组合式API使用axios的写法,ref定义响应数据写法
    28
  • 8
    网页设计,若依项目修改(It must be done)02------axios封装后发get请求,axios请求的位置在呢?
    45
  • 9
    前后端数据交互之axios的路径怎样找?axios的路径是那个,是你打开Tomcat之后,出现的路径+你项目写的接口路径
    34
  • 10
    数据交互,前后端数据请求,axios请求,对象结构的使用,E6的使用,结构赋值是什么?函数形参的obj如何,函数形参的obj就改成对象结构接收传入的数据对象
    25