接口请求节流限制

1. 节流意义

 1. 前端调用接口时,有时通过接口会多次连续调用后端接口,这样会增加后端的响应负载,也会占用服务数据传出的带宽,造成资源的浪费

2. 实现方式

1. 通用实现将相同url,请求方式,请求参数三者作为缓存key,每次请求接口时将该key存入缓存对象中,接口响应完成后从缓存对象里移除该key

2. 发送请求时通过从缓存对象里用key获取值,如果获取到有值则该请求已请求过还未请求完成,则中断该次的请求

3. 实现代码

1. 新建throttleHttp.js

// 新建map用于存放正在执行的请求
const pendingRequest = new Map()

class throttleHttp {
  constructor(originalAxios) {
    this.originalAxios = originalAxios
  }

  // generateReqKey:用于根据当前请求的信息,生成请求Key存放到map中作为当前请求的键;
  generateReqKey(config) {
    let { method, url, params, data } = config
    if (typeof params === 'string') {
      params = JSON.parse(params)
    }
    if (typeof data === 'string') {
      data = JSON.parse(data)
    }
    // return [method, url.replace(config.baseURL, ''), JSON.stringify(params), JSON.stringify(data)].join('&')
    return [method, url.replace(`${config.baseURL}/`, ''), JSON.stringify(params), JSON.stringify(data)].join('&')
  }

  // addPendingRequest:用于把当前请求信息添加到pendingRequest对象中
  addPendingRequest(config) {
    const requestKey = this.generateReqKey(config)
    // 这下面的部分不能去除的原因是因为在清空所有请求的时候需要用到cancel令牌
    // 所以必须在添加请求的时候就创建一个CancelToken取消令牌用于之后clearPending函数清空请求
    const originalAxios = this.originalAxios
    config.cancelToken = new originalAxios.CancelToken((cancel) => {
      // 创建当前请求放到map中
      pendingRequest.set(requestKey, cancel)
    })
  }

  // 去除所有列表里的请求(用于跳转路由等需要清空请求的情况)
  clearPending() {
    // 遍历map对象,用每个取消令牌逐一取消请求,起到清空所有请求的作用
    for (const [requestKey, cancelToken] of pendingRequest) {
      cancelToken(requestKey)
    }
    // 清空map对象
    pendingRequest.clear()
  }

  pendingReqHasKey(key) {
    return pendingRequest.has(key)
  }

  pendingReqdelKey(key) {
    pendingRequest.delete(key)
  }
}

export default throttleHttp

2. 在封装的axios引用hrottleHttp.js


import axios from 'axios'

/* eslint-disable */
const ThrottleHttp = new throttleHttp(axios)
axios.defaults.timeout = 86400000
axios.defaults.baseURL = basePublicUrl
axios.defaults.withCredentials = false
axios.defaults.headers.post['Content-Type'] = 'application/json'


// 如果走全局网关,看是否进行加密
// 请求拦截
axios.interceptors.request.use(function (config) {
  // 生成请求key
  const requestKey = ThrottleHttp.generateReqKey(config)
  if (ThrottleHttp.pendingReqHasKey(requestKey)) {
    return httpMark
  }
  // 把当前请求信息添加到pendingRequest对象中
  ThrottleHttp.addPendingRequest(config)
  return config
}, function (error) {
  // 这里出现错误可能是网络波动造成的,清空 pendingRequests 对象
  ThrottleHttp.clearPending()
  return Promise.reject(error.response)
})
axios.interceptors.response.use(function (response) {
  // 删除收集的请求key
  const requestKey = ThrottleHttp.generateReqKey(response.config)
  // 根据key删除当前请求
  ThrottleHttp.pendingReqdelKey(requestKey)
  // 收集报错信息
  return response
}, function (error) {
  // 删除收集的请求key
  const requestKey = ThrottleHttp.generateReqKey(error.config)
  //根据key删除当前请求
  ThrottleHttp.pendingReqdelKey(requestKey)
  return error
})

猜你喜欢

转载自blog.csdn.net/weixin_46996561/article/details/129917730