在Vue3+Ts项目中封装axios
说明
采用了类封装思想,包含了三种情况的拦截器封装
①公共拦截器(所有实例都有的拦截器)
②特有拦截器(只有在new实例时传入的对象中传入了拦截器)
③独有拦截器(只有在调用请求的时候传入拦截器)
实现代码
在用cli脚手架创建完成项目后
在src下面创建network文件夹,在里面创建index.ts
该文件是拿到axios请求封装实例并导出使用(网络请求出口)
// src/network/index.ts
// network的统一出口
import NWRequest from './request'
// 这里是有传入特有拦截器的实例
const nwRequest = new NWRequest({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: process.env.VUE_APP_TIME_OUT,
interceptors: {
requestInterceptor: (config) => {
console.log('在new实例时有传入拦截器的实例才有的拦截器:请求成功的拦截')
return config
},
requestInterceptorCatch: (err) => {
console.log('在new实例时有传入拦截器的实例才有的拦截器:请求失败的拦截')
return err
},
responseInterceptor: (config) => {
console.log('在new实例时有传入拦截器的实例才有的拦截器:响应成功的拦截')
return config
},
responseInterceptorCatch: (err) => {
console.log('在new实例时有传入拦截器的实例才有的拦截器:响应失败的拦截')
return err
}
}
})
// 这里是没有有传入特有拦截器的实例
const nwRequest1 = new NWRequest({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: process.env.VUE_APP_TIME_OUT
})
export { nwRequest, nwRequest1 }
在src的network下创建request文件夹,在里面创建type.ts
该文件是为了定义ts的限制类型接口interface
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
interface NWRequestInterceptors<T = AxiosResponse> {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: any) => any
responseInterceptor?: (res: T) => T
responseInterceptorCatch?: (error: any) => any
}
interface NWRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: NWRequestInterceptors<T>
}
export { NWRequestInterceptors, NWRequestConfig }
在src的network下的request文件夹,在里面创建index.ts
该文件是axios主要封装类
// src/network/request/index.ts
import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { NWRequestInterceptors, NWRequestConfig } from './type'
// 定义网络请求的封装类
class NWRequest {
instance: AxiosInstance
interceptors?: NWRequestInterceptors
constructor(config: NWRequestConfig) {
this.instance = axios.create(config)
this.interceptors = config.interceptors
// 从config中取出的拦截器是对应的实例的拦截器
// 只有new实例的时候有传入拦截器才有
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatch
)
this.instance.interceptors.response.use(
this.interceptors?.responseInterceptor,
this.interceptors?.responseInterceptorCatch
)
// 添加所有的实例都有的拦截器
this.instance.interceptors.request.use(
(config) => {
console.log('所有的实例都有的拦截器:请求成功拦截')
return config
},
(err) => {
console.log('所有的实例都有的拦截器:请求失败拦截')
return err
}
)
this.instance.interceptors.response.use(
(res) => {
console.log('所有的实例都有的拦截器:响应成功拦截')
return res
},
(err) => {
console.log('所有的实例都有的拦截器:响应失败拦截')
return err
}
)
}
request<T>(config: NWRequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
// 这里的作用是,如果在调用请求的时候想添加额外单独的拦截器
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
this.instance
.request<any, T>(config)
.then((res) => {
if (config.interceptors?.responseInterceptor) {
res = config.interceptors.responseInterceptor(res)
}
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
get<T>(config: NWRequestConfig<T>): Promise<T> {
return this.request<T>({
...config,
method: 'GET'
})
}
post<T>(config: NWRequestConfig<T>): Promise<T> {
return this.request<T>({
...config,
method: 'POST'
})
}
}
export default NWRequest
测试
在src下的main.ts中
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { nwRequest } from './network'
const app = createApp(App)
app.use(router)
app.use(store)
app.mount('#app')
// 该请求包含公共拦截器、特有拦截器
nwRequest.request({
url: '/login',
method: 'POST',
data: {
name: '哈哈哈',
password: '123456'
}
})
nwRequest
.post({
url: '/login',
data: {
name: '哈哈哈',
password: '123456'
}
})
.then((res) => {
console.log(res)
})
// 该请求包含公共拦截器、独有拦截器
// nwRequest1.request({
// url: '/login',
// method: 'POST',
// data: {
// name: '哈哈哈',
// password: '123456'
// },
// interceptors: {
// requestInterceptor: (config) => {
// console.log('独有拦截器:单独请求的config')
// return config
// }
// }
// })
// 该请求质只包含公共拦截器
// nwRequest1.request({
// url: '/login',
// method: 'POST',
// data: {
// name: '哈哈哈',
// password: '123456'
// }
// })
\