VUE3 AXIOS 封装

网上找了很多AXIOS的封装但是都不是很满意,后来参考其他人的实现做了改动后特分享出来

http.ts 文件封装

import type { AxiosRequestConfig, AxiosResponse } from 'axios'
import axios from 'axios'

const service = axios.create({
  baseURL: import.meta.env.VITE_HOST,
  headers: {
    'Content-Type': 'application/json'
  },
  // 是否跨站点访问控制请求
  withCredentials: false,
  timeout: 30000,
  transformRequest: [(data, headers) => {
    //Content-Type:"multipart/form-data"
    if (headers["Content-Type"] == "application/json") {
      data = JSON.stringify(data)
    }
    return data
  }],
  validateStatus() {
    // 使用async-await,处理reject情况较为繁琐,所以全部返回resolve,在业务代码中处理异常
    return true
  },
  transformResponse: [(data) => {
    if (typeof data === 'string' && data.startsWith('{')) {
      data = JSON.parse(data)
    }
    return data
  }]
})

// 声明一个 Map 用于存储每个请求的标识 和 取消函数
const pending = new Map()
/**
 * 添加请求
 * @param {Object} config 
 */
const addPending = (config: AxiosRequestConfig) => {
  const url = [
    config.method,
    config.url,
    config.params,
    config.data
  ].join('&')
  config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
    if (!pending.has(url)) { // 如果 pending 中不存在当前请求,则添加进去
      pending.set(url, cancel)
    }
  })
}

/**
 * 移除请求
 * @param {Object} config 
 */
const removePending = (config: AxiosRequestConfig) => {
  const url = [
    config.method,
    config.url,
    config.params,
    config.data
  ].join('&')
  if (pending.has(url)) { // 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
    const cancel = pending.get(url)
    cancel(url)
    pending.delete(url)
  }
}

/**
 * 清空 pending 中的请求(在路由跳转时调用)
 */
export const clearPending = () => {
  for (const [url, cancel] of pending) {
    cancel(url)
  }
  pending.clear()
}

/**
 * 请求拦截器
 */
service.interceptors.request.use((config: AxiosRequestConfig) => {
  removePending(config) // 在请求开始前,对之前的请求做检查取消操作
  addPending(config) // 将当前请求添加到 pending 中
  let token = localStorage.getItem('__TOKEN__')
  if (token && config.headers) {
    // 服务端 Bearer JWT 要求 Bearer前缀
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config
}, 
(error) => {
  // 错误抛到业务代码
  error.data = {}
  error.data.msg = '服务器异常,请联系管理员!'
  return Promise.resolve(error)
})

/**
 * 响应拦截器
 *  */ 
service.interceptors.response.use(
  (response: AxiosResponse) => {

    removePending(response.config); // 在请求结束后,移除本次请求
    const status = response.status
    let msg = ''
    if (status < 200 || status >= 300) {
      // 处理http错误,抛到业务代码
      // msg = showStatus(status)
      if (typeof response.data === 'string') {
        response.data = { msg }
      } else {
        response.data.msg = msg
      }
    }

    // 续签TOKEN
    if (response.headers && response.headers.authorization) {
      localStorage.setItem('__TOKEN__', response.headers.authorization)

    }

    return response
  },
  (error) => {
    if (axios.isCancel(error)) {
      console.log('repeated request: ' + error.message)
    } else {
      // handle error code
      // 错误抛到业务代码
      error.data = {}
      error.data.msg = '请求超时或服务器异常,请检查网络或联系管理员!'
      // ElMessage.error(error.data.msg)
    }
    return Promise.reject(error)
  })

export default service


 

Service封装: MediaService.ts

import Axios from 'http';
import type { HttpResponse } from './HttpResponse';
import type { AxiosProgressEvent } from 'axios';


export class MediaService {

    /**
     * 上传文件
     */
    static async UploadFile(data: any): Promise<HttpResponse<any>> {

        let fileName = data.file.name;

        let formData = new FormData();
        formData.append('file', data.file, fileName)

        return Axios('http://localhost:29322/api/...', {
            method: 'post',
            headers: {
                'Content-Type': 'multipart/form-data'
            },
            responseType: 'json',
            data: formData,
            onUploadProgress(args: AxiosProgressEvent) {
                if (args.total) {
                    data.onProgress({ percent: Math.round((args.loaded / args.total) * 100) }, data.file);
                }
            }
        });
    }

    static async AddLibrary(data: any): Promise<HttpResponse<any>> {
        return Axios('http://localhost:29322/api/...', {
            method: 'post',
            responseType: 'json',
            data: data            
        });
    }
}

 

VUE页面调用参考

import { MediaService } from 'MediaService';


MediaService.AddLibrary(formState).then(res => {
   // ...
});

MediaService.UploadFile(data).then(res => {
     // ...
});

 

其他相关文件  HttpResponse.ts

export interface HttpResponse<T> {
  status: number
  statusText: string
  data: {
    code: number
    message: string
    data:T
    [key: string]: any
  }
}

 

posted @ 2023-01-09 23:01  moonwebmast  阅读(1769)  评论(0编辑  收藏  举报