typescript对与axios的封装

import { Modal, message } from 'antd'
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'

import AdminConfig from '@/common/config'
import { getToken } from './cookie'

interface ResponseData<T extends any> {
  data: T
  errorMsg: number
  message: string
}

declare module 'axios' {
  export interface AxiosRequestConfig {
    currentRequestList: string[]
    timeStep: number
    currentCount: number
    MaxReconnectionTimes: number
    loading: boolean
    submit: boolean
  }
}

const service = axios.create({
  // 接口地址前缀
  baseURL: __PROD__ ? AdminConfig.apiUrl : '',
  // 超时时间
  timeout: 500,
  // 当前同一时间内同时并行请求接口
  currentRequestList: [],
  // 重连间隔
  timeStep: 500,
  // 当前重连次数
  currentCount: 1,
  // 最大重连次数
  MaxReconnectionTimes: 5,
  // 重连机制开启时所有接口都不可在同一时间平行访问
  loading: false,
  // 重复提交控制
  submit: false,
})

/**
 * 清除当前请求的ajax
 * @param url
 */
function clearRequestStatus(url: string): void {
  service.defaults.loading = false
  const index = service.defaults.currentRequestList.indexOf(url)

  // eslint-disable-next-line @typescript-eslint/no-magic-numbers
  if (index > -1) {
    service.defaults.currentRequestList.splice(index, 1)
  }
}

/**
 * @param url
 * @param data
 * @param submit
 * @param loading
 * @returns {Promise<postcss.Result> | Q.Promise<any>}
 */
// eslint-disable-next-line max-len
export function httpServer(url: string, data: any, submit = false, loading = false): any {
  return service({
    ...service.defaults,
    url,
    data,
    submit,
    loading
  })
}

// 请求拦截
service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    const token = getToken()

    if (token) {
      // eslint-disable-next-line no-param-reassign
      config.headers.token = token
    }
    const { submit, url } = config

    if (submit) {
      if (service.defaults.currentRequestList.includes(String(url))) {
        return Promise.reject(message.info(`${url}正在请求,请勿重复提交`))
      }
      service.defaults.currentRequestList.push(String(url))
    }
    if (service.defaults.loading && !config.loading) {
      return Promise.reject(message.info('当前网络不佳,正在为您拼命加载...'))
    }

    // 对config处理完后返回,下一步将向后端发送请求
    return config
  },
  async (error: AxiosError) => Promise.reject(error),

)


axios.interceptors.response.use(
  (response: AxiosResponse<ResponseData<any>>) => {
    // 登录已过期或者未登录
    if (response.data.errorMsg === AdminConfig.loginExpire) {
      Modal.confirm({
        title: '系统提示',
        content: response.data.message,
        okText: '重新登录',
        onOk() {

          // 登出与首页跳转
          // store.dispatch(logout())
        },
      })

      return Promise.reject(new Error(response.data.message))
    }

    // 请求成功
    if (response.data.errorMsg === AdminConfig.successCode) {
      return response.data as any
    }


    return Promise.reject(new Error(response.data.message))
  },
  // eslint-disable-next-line complexity
  async (error: AxiosError) => {
    const { config } = error

    if (config.submit) {
      clearRequestStatus(String(config.url))
    }
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    if (error.message.search('timeout') > -1) {
      const { MaxReconnectionTimes, currentCount, timeStep } = service.defaults

      // 可自行在这里配置showTitle弹出框展示
      message.info(`当前网络不佳...已尝试为您重连第${currentCount}次`)
      if (MaxReconnectionTimes <= currentCount) {
        return Promise.reject(error)
      }
      const Reconnection = new Promise((resolve) => {
        setTimeout(() => {
          service.defaults.currentCount += 1
          resolve()
        }, timeStep || 1000)
      })

      const {url, data } = config

      return Reconnection.then(() => {
        service.defaults.loading = true
        httpServer(String(url), data, true, true)
      })
    }

    return Promise.reject(error)
  },
)

export default service


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值