Skip to content

请求封装,请求频繁取消上一次请求,封装失败重试


js
import axios from 'axios'

const request = axios.create({
  timeout: 5000,
  data: {},
  params: {},
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

// 声明一个数组用于存储每个ajax 请求标志, 重复请求时取消上一次请求
const pendingMap = new Map()
const CancelToken = axios.CancelToken
const removePending = ever => {
  // 删除该请求在 pending 中的记录
  let key = `${ever.url}&${JSON.stringify(ever.params)}&${JSON.stringify(ever.data)}&${ever.method}`
  if (pendingMap.has(key)) {
    pendingMap.get(key)()
    pendingMap.delete(key)
  }
}

// 请求拦截
request.interceptors.request.use(
  config => {
    // 在ajax 发送前,取消该接口的上一次请求
    removePending(config)
    config.cancelToken = new CancelToken(cancel => {
      // 构造 ajax 请求标志
      const url = `${config.url}&${JSON.stringify(config.params)}&${JSON.stringify(config.data)}&${config.method}`
      pendingMap.set(url, cancel)
    })
    return config
  },
)

// 重试次数
const retry = 2
// 重试延迟
const retryDelay = 500

// 返回拦截
request.interceptors.response.use(
  response => {
    // 请求成功之后,把请求标志从pending 队列中删除
    removePending(response.config)
    return response.data
  },
  err => {
    // ! 请求错误重试
    const config = err.config
    // 没有请求次数,或者重试次数结束则直接返回错误
    if (!config || !retry || config.retryCount >= retry) {
      return Promise.reject(err)
    }
    config.retryCount = config.retryCount || 0
    // console.log(`第${config.retryCount + 1}次重试`)
    config.retryCount += 1
    const backoff = new Promise(resolve => {
      setTimeout(() => {
        resolve()
      }, retryDelay)
    })

    return backoff.then(() => {
      return request(config)
    })
  }
)

export default request

Released under the MIT License.