1. 目录层级
- axios
- request
- config.ts
- index.ts
- types.ts
- index.ts
2. 具体代码
2.1 request/types
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
export interface CustomInterceptors<T = AxiosResponse> {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (err: any) => any
responsetInterceptor?: (config: T) => T
responsetInterceptorCatch?: (err: any) => any
}
export interface CustomRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: CustomInterceptors<T>
showLoading?: boolean
}
2.2 request/config
export const TIME_OUT = 1000
export const API_BASE_URL = process.env.VUE_APP_BASE_URL
2.3 request/index
import axios from 'axios'
import type { AxiosInstance } from 'axios'
import { ElLoading } from 'element-plus'
import type { LoadingInstance } from 'element-plus/lib/components/loading/src/loading'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { CustomInterceptors, CustomRequestConfig } from './types'
const DEFAULT_LOADING = false
class HttpRequest {
instance: AxiosInstance
interceptors?: CustomInterceptors
showLoading: boolean
loading?: LoadingInstance
constructor(config: CustomRequestConfig) {
this.instance = axios.create(config)
this.showLoading = config.showLoading ?? DEFAULT_LOADING
this.interceptors = config.interceptors
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatch
)
this.instance.interceptors.response.use(
this.interceptors?.responsetInterceptor,
this.interceptors?.responsetInterceptorCatch
)
this.instance.interceptors.request.use(
(config) => {
NProgress.start()
if (this.showLoading) {
this.loading = ElLoading.service({
lock: true,
text: '正在加载...',
background: 'rgba(0, 0, 0, 0.5)'
})
}
return config
},
(error) => {
return error
}
)
this.instance.interceptors.response.use(
(res) => {
this.loading?.close()
NProgress.done()
return res
},
(error) => {
this.loading?.close()
NProgress.done()
return error
}
)
}
request<T = any>(config: CustomRequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
if (config.showLoading === true) {
this.showLoading = config.showLoading
}
this.instance
.request<any, T>(config)
.then((res) => {
if (config.interceptors?.responsetInterceptor) {
res = config.interceptors.responsetInterceptor(res)
}
this.showLoading = DEFAULT_LOADING
resolve(res)
})
.catch((error) => {
this.showLoading = DEFAULT_LOADING
reject(error)
})
})
}
get<T = any>(config: CustomRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'GET' })
}
post<T = any>(config: CustomRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'POST' })
}
put<T = any>(config: CustomRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'PUT' })
}
delete<T = any>(config: CustomRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'DELETE' })
}
}
export default HttpRequest
2.4 axios/index
import HttpRequest from './request'
import { API_BASE_URL, TIME_OUT } from './request/config'
import { tokenCatch } from '@/utils/catch'
import { isCheckTimeout } from '@/utils/auth'
import { useLoginStore } from '@/store'
import { ElMessage } from 'element-plus'
import { setTimeStamp, getAccessHeader } from '@/utils/auth'
import router from '@/router'
const httpRequest = new HttpRequest({
baseURL: API_BASE_URL,
timeout: TIME_OUT,
interceptors: {
requestInterceptor(config) {
const TOKEN = tokenCatch.get()
if (TOKEN) {
if (isCheckTimeout()) {
const loginStore = useLoginStore()
loginStore.clearUserCatchAction()
ElMessage.error('登录超时!')
Promise.reject(new Error('登录超时!'))
}
config.headers!.token = TOKEN
}
return config
},
requestInterceptorCatch(error) {
return error
},
responsetInterceptor(res) {
const blackList = [401, 404, 500, 403]
const { code, message = '' } = res.data
if (blackList.includes(code)) {
ElMessage.error(message)
if (code === 401) {
const loginStore = useLoginStore()
loginStore.clearUserCatchAction()
} else if (code === 403) {
} else {
router.push('/404')
}
return Promise.reject(new Error(message))
}
if (code === 400) {
ElMessage.warning(message)
}
setTimeStamp()
const NEW_TOKEN = res.headers?.token ?? ''
getAccessHeader(NEW_TOKEN)
return res.data
},
responsetInterceptorCatch(error) {
if (error.code === 'ERR_NETWORK') {
ElMessage.error('当前网络错误,请稍后再试')
}
if (error && error.code === 'ECONNABORTED') {
ElMessage.error({ message: error.message, customClass: 'custom-message' })
}
return error
}
}
})
export default httpRequest