vue3中axios请求封装

134 阅读1分钟
utils/http/index.ts
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'
import { showMessage } from './status'
import { ElMessage } from 'element-plus'
import { UserStore } from '@/store'
import router from '@/router'

const config = {
  // 默认地址
  // baseURL: import.meta.env.VITE_APP_URL as string,
  // @ts-ignore
  baseURL: window.appsettings.baseUrl_JAVA,
  // 设置超时时间(60s)
  timeout: 10 * 60000,
  // 跨域时候允许携带凭证
  withCredentials: true,
  headers: {
    ' Cache-Control': 'no-cache'
  }
}
interface CustomAxiosRequestConfig extends AxiosRequestConfig {
  noAuth?: boolean
}
class RequestHttp {
  service: AxiosInstance
  public constructor(config: CustomAxiosRequestConfig) {
    // 实例化axios
    this.service = axios.create(config)

    /**
     * @description 请求拦截器
     * 客户端发送请求 -> [请求拦截器] -> 服务器
     * token校验(JWT) : 接受服务器返回的token,存储到vuex/本地储存当中
     */

    this.service.interceptors.request.use(
      // @ts-ignore
      (config: CustomAxiosRequestConfig) => {
        const userStore = UserStore()
        const token = userStore.access_token

        if (token && !config.noAuth) {
          // @ts-ignore
          config.headers.Authorization = `Bearer ${token}`
        }

        return { ...config }
      },
      (error: AxiosError) => {
        return Promise.reject(error)
      }
    )

    /**
     * @description 响应拦截器
     *  服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
     */
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
        if (response.config.url?.includes('/exe/download')) return response
        const { data } = response
        return data
      },
      async (error: AxiosError) => {
        const { message, response, code } = error
        // 这一步就是进行错误弹框处理,
        const isBlob = response?.data instanceof Blob
        if (isBlob) {
          const fileMessage = await BlobToObject(response?.data)
          ElMessage({
            message: fileMessage as string,
            type: 'error'
          })
          return
        }
        if (response && response.status == 401) {
          localStorage.clear()
          const userStore = UserStore()
          userStore.resetInfo()
          ElMessage({ message: '用户状态已失效,请重新登录!', type: 'error' })
          router.push('/home')
          return
        }
        if (response && response.status == 415) {
          localStorage.clear()
          const userStore = UserStore()
          userStore.resetInfo()
          ElMessage({ message: response.data as string, type: 'error' })
          router.push('/401')
          return
        }
        if (response || message) {
          console.log('response', response)
          let msg = response
            ? response.data && typeof response.data == 'string'
              ? response.data
              : showMessage(response.status)
            : message
          if (msg.toString().length > 100 || !msg) msg = `服务器发生错误,错误代码:${code}`
          ElMessage({ message: msg, type: 'error' })
        }
        return Promise.reject(error)
      }
    )
  }

  // * 常用请求方法封装
  get<T>(url: string, params?: object, _object = {}): Promise<T> {
    return this.service.get(url, { params, ..._object })
  }
  post<T>(url: string, params?: object, _object = {}): Promise<T> {
    return this.service.post(url, params, _object)
  }
  put<T>(url: string, params?: object, _object = {}): Promise<T> {
    return this.service.put(url, params, _object)
  }
  delete<T>(url: string, params?: any, _object = {}): Promise<T> {
    return this.service.delete(url, { params, ..._object })
  }
  patch<T>(url: string, params?: any, _object = {}): Promise<T> {
    return this.service.patch(url, { params, ..._object })
  }
}

function BlobToObject(blob: any) {
  return new Promise(resolve => {
    try {
      const { type } = blob
      if (type === 'application/json') {
        const file = new FileReader()

        file.readAsText(blob, 'utf-8')
        file.onload = function () {
          resolve(file.result as string)
        }
      } else {
        resolve('文件下载失败')
      }
    } catch (err) {
      resolve('文件下载失败')
    }
  })
}
export default new RequestHttp(config)

使用 api/apiFun.ts
import http from '@/utils/http'
import { UserStore } from '@/store'
import { filterParam } from '@/utils/index'
export const apiFun = (moduleUrl: string) => {
  const url = window.appsettings.baseUrl_JAVA + moduleUrl
  const addFun = (data: any) => {
    return http.post(url, data)
  }

  const updateFun = (data: any) => {
    return http.post(`${url}/update`, data)
  }
  const updateFunItem = (data: any) => {
    return http.put(`${url}`, data)
  }
  const updateFunOne = (id: number, data: any) => {
    return http.put(`${url}/${id}`, data)
  }

  const deleteFun = (id: number) => {
    return http.delete(`${url}/${id}`)
  }

  const findByIdFun = (id: number) => {
    return http.get(`${url}/${id}`)
  }
  const findListFunc = (params: Object) => {
    return http.get(`${url}/list`, params)
  }
  const findListFun = <U extends object | undefined, T>(params?: U) => {
    const userStore = UserStore()
    let tempparams = { createdBy: userStore.userId }
    if (params) {
      tempparams = { ...tempparams, ...params }
    }
    return http.get<T>(`${url}/list`, tempparams)
  }
  const exportDataFun = (params: any) => {
    return http.service({
      url: `${url}/export`,
      method: 'get',
      params,
      responseType: 'blob'
    })
  }

  const importDataFun = (data: any) => {
    return http.post(`${url}/import`, data)
  }
  return {
    addFun,
    updateFun,
    updateFunItem,
    updateFunOne,
    deleteFun,
    findByIdFun,
    findListFun,
    exportDataFun,
    importDataFun,
    findListFunc
  }
}

vue文件中使用
import { apiFun } from '@/api/apiFun'
const gainApi = apiFun('/gain')
gainApi.addFun(params).then(res=>{})