axios
axios的基本使用
-
调用axios,传入一个url后会返回一个类型为
-
AxiosResponse的promise类型(已经执行了resolev和reject判断)
-
用人话说就是axios将请求数据包裹在promise中返回
axios .get('http://httpbin.org/get', { params: { name: 'codermjjh', age: '18' } }) .then((res) => { console.log(res.data) }) axios .post('http://httpbin.org/post', { data: { name: 'codermjjh', age: '18' } }) .then((res) => { console.log(res.data) })
axios的全局配置
// axios的全局配置选项
// 默认url
axios.defaults.baseURL = 'http://httpbin.org'
// 超时时间
axios.defaults.timeout = 10000
axios
.get('/get', {
params: {
name: 'codermjjh',
age: '18'
}
})
.then((res) => {
console.log(res.data)
})
axios
.post('/post', {
data: {
name: 'codermjjh',
age: '18'
}
})
.then((res) => {
console.log(res.data)
})
axios.all
// axios.all(就是用的promise里的方法)
axios
.all([
axios.get('/get', { params: { name: 'codermjjh', age: 18 } }),
axios.post('/post', { data: { name: 'codermjjh', age: 18 } })
])
.then((res) => {
console.log(res[0].data)
console.log(res[1].data)
})
拦截器
// axios的拦截器
// f1在请求发送成功时候会执行的函数
// f2在请求发送失败时候会执行的函数
axios.interceptors.request.use(
(config) => {
// 想做的一些事情
// 给请求添加token
// 触发加载动画
console.log('请求成功的拦截')
return config
},
(config) => {
console.log('请求失败的拦截')
}
)
// f1数据响应成功时候会执行的函数
// f2数据响应失败时候会执行的函数
axios.interceptors.response.use(
(res) => {
console.log('响应成功的拦截')
return res
},
(err) => {
console.log('响应失败的拦截' + err)
}
)
封装axios
基础功能封装
核心代码
// 核心处理代码
// AxiosInstance AxiosRequestConfig是官方的类型,需要从axios库中引入
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
class MJRequest {
// 1 定义instance类型
private instance: AxiosInstance
// 2 在new过程中使constructor获取到对应的公共属性
constructor(config: AxiosRequestConfig) {
this.instance = axios.create(config)
}
// 3 获取对应的路径请求参数,携带的参数,请求方式
// 然后发送请求,获取到请求结果
request(config: AxiosRequestConfig): void {
this.instance.request(config).then((res) => {
console.log(res)
})
}
}
export default MJRequest
公共属性配置
import MJRequest from './request'
// 主要功能是配置一些公共属性
// 比如 baceUrl 超时时间等
const mjRequest = new MJRequest({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: process.env.VUE_APP_TIME_OUT
})
export default mjRequest
外部文件使用
import mjRequest from './service'
// 需要传入具体的路径,携带的参数,请求方式等
mjRequest.request({
url: '/home/multidata',
method: 'GET'
})
代码结构
拦截器封装
由于开发中不仅仅需要配置公共属性,还需要监听一些loading事件(等待请求返回的转圈圈)类似事件,所以需要在外部对拦截器进行监听
拦截器有四种对应以下几种状态
| requestInterceptor | 请求成功的拦截 |
|---|---|
| requestInterceptorCatch | 请求失败的拦截 |
| responseInterceptor | 响应成功的拦截 |
| responseInterceptorCatch | 响应失败的拦截 |
-
添加自定义拦截器类型
interface MJRequestInterceptors { requestInterceptor: (config: AxiosRequestConfig) => AxiosRequestConfig requestInterceptorCatch: (error: any) => any responseInterceptor: (res: AxiosResponse) => AxiosResponse responseInterceptorCatch: (error: any) => any } -
定义自己的类型 继承axios原始类型的同时集成自定义拦截器的类型
interface MJRequestConfig extends AxiosRequestConfig {
interceptors: MJRequestInterceptors
}
- 引入类型 并且替换new创建时constructor传入的类型 最后实现拦截器方法
private interceptors: MJRequestInterceptors
constructor(config: MJRequestConfig) {
this.instance = axios.create(config)
this.interceptors = config.interceptors
this.instance.interceptors.request.use(
this.interceptors.requestInterceptor,
this.interceptors.requestInterceptorCatch
)
this.instance.interceptors.response.use(
this.interceptors.responseInterceptor,
this.interceptors.responseInterceptorCatch
)
}
- 可选
由于用户也有可能不需要使用拦截器功能,所以拦截器功能应该是可选的
核心代码
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
// 添加自定义拦截器类型
interface MJRequestInterceptors {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: any) => any
responseInterceptor?: (res: AxiosResponse) => AxiosResponse
responseInterceptorCatch?: (error: any) => any
}
// 定义自己的类型 继承axios原始类型的同时集成自定义拦截器的类型
interface MJRequestConfig extends AxiosRequestConfig {
interceptors?: MJRequestInterceptors
}
class MJRequest {
// 引入类型
private instance: AxiosInstance
private interceptors?: MJRequestInterceptors
// 创建MJREsquest时候传入的选项
constructor(config: MJRequestConfig) {
this.instance = axios.create(config)
// 实现拦截器方法
this.interceptors = config.interceptors
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatch
)
this.instance.interceptors.response.use(
this.interceptors?.responseInterceptor,
this.interceptors?.responseInterceptorCatch
)
}
// 调用函数发出请求
request(config: AxiosRequestConfig): void {
this.instance.request(config).then((res) => {
console.log(res)
})
}
}
export default MJRequest
公共属性+拦截器配置
import MJRequest from './request'
const mjRequest = new MJRequest({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: process.env.VUE_APP_TIME_OUT,
interceptors: {
requestInterceptor: (config) => {
console.log('请求成功的拦截')
return config
},
// requestInterceptorCatch: (err) => {
// console.log('请求失败的拦截')
// return err
// },
responseInterceptor: (res) => {
console.log('响应成功的拦截')
return res
}
// responseInterceptorCatch: (err) => {
// console.log('响应失败的拦截')
// return err
// }
}
})
export default mjRequest
外部调用
import mjRequest from './service'
// 需要传入具体的路径,携带的参数,请求方式等
mjRequest.request({
url: '/home/multidata',
method: 'GET'
})
分层处理拦截
由于在开发种会遇到对全局请求,单实例请求,单个请求等不同的拦截场景,所以需要对多出进行拦截请求
所以添加了所有实例都会触发的拦截器和单个请求可选的拦截器
-
添加所有实例都会触发的拦截器
// 添加所有实例都有的拦截器 this.instance.interceptors.request.use( (config) => { console.log('All_Request_success') return config }, (err) => { console.log('All_Request_error') return err } ) this.instance.interceptors.response.use( (config) => { console.log('All_Response_success') return config }, (err) => { console.log('All_Response_error') return err } ) -
添加单个请求可选的拦截器
判断传入的参数是否有携带insterceptors属性
request(config: MJRequestConfig): void { // 单个请求的拦截器 if (config.interceptors?.requestInterceptor) { config = config.interceptors.requestInterceptor(config) } this.instance.request(config).then((res) => { if (config.interceptors?.responseInterceptor) { config = config.interceptors.responseInterceptor(res) } console.log(res) }) }
核心代码
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
// 添加自定义拦截器类型
interface MJRequestInterceptors {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: any) => any
responseInterceptor?: (res: AxiosResponse) => AxiosResponse
responseInterceptorCatch?: (error: any) => any
}
// 定义自己的类型 继承axios原始类型的同时集成自定义拦截器的类型
interface MJRequestConfig extends AxiosRequestConfig {
interceptors?: MJRequestInterceptors
}
class MJRequest {
// 引入类型
private instance: AxiosInstance
private interceptors?: MJRequestInterceptors
// 创建MJREsquest时候传入的选项
constructor(config: MJRequestConfig) {
this.instance = axios.create(config)
// 实现拦截器方法
this.interceptors = config.interceptors
// 单个实例独有的拦截器
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('All_Request_success')
return config
},
(err) => {
console.log('All_Request_error')
return err
}
)
this.instance.interceptors.response.use(
(config) => {
console.log('All_Response_success')
return config
},
(err) => {
console.log('All_Response_error')
return err
}
)
}
// 调用请求发出请求
request(config: MJRequestConfig): void {
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
this.instance.request(config).then((res) => {
if (config.interceptors?.responseInterceptor) {
config = config.interceptors.responseInterceptor(res)
}
console.log(res)
})
}
}
export default MJRequest
公共属性+拦截器配置
import MJRequest from './request'
const mjRequest = new MJRequest({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: process.env.VUE_APP_TIME_OUT,
interceptors: {
requestInterceptor: (config) => {
console.log('请求成功的拦截')
return config
},
// requestInterceptorCatch: (err) => {
// console.log('请求失败的拦截')
// return err
// },
responseInterceptor: (res) => {
console.log('响应成功的拦截')
return res
}
// responseInterceptorCatch: (err) => {
// console.log('响应失败的拦截')
// return err
// }
}
})
export default mjRequest
外部调用
mjRequest.request({
url: '/home/multidata',
method: 'GET',
interceptors: {
requestInterceptor: (config) => {
console.log('单独请求的config')
return config
},
responseInterceptor: (res) => {
console.log('单独响应的response')
return res
}
}
})
携带Token
错误返回
在全局拦截器下,监听返回数据的状态码
this.instance.interceptors.response.use(
(res) => {
console.log('All_Response_success')
switch (res.data.returnCode) {
case '-1001':
console.log('请求失败错误信息....')
break
// 以此类推...
default:
break
}
return res.data
},
(err) => {
console.log('All_Response_error')
switch (err.response.status) {
case 404:
console.log('404错误...')
break
// 以此类推...
default:
break
}
return err
}
)
组件loading加载
-
引入element plus
在代码中声明elementPlus组件时候需要对其做一次引入,同时需要引入其内的css样式
import { ElLoading } from 'element-plus' // 在代码中引用需要手动导入对应组件的样式 import 'element-plus/es/components/loading/style/css'路径不是绝对的随着版本更新会改变,所以建议去翻elementPlus源码
-
使用loading
在全局拦截器中声明
this.instance.interceptors.request.use( (config) => { console.log('All_Request_success') if (this.showLoading) { this.loading = ElLoading.service({ lock: true, text: '努力搬运中', background: 'rgba(0,0,0,0.5)' }) } return config }, (err) => { console.log('All_Request_error') return err } ) -
停止loading事件
在请求响应完毕之后需要停止loading事件,由于typescript的原因我们需要引入loading的类型
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading'这里的路径也不是绝对的建议翻看elementPlus源码
// 最终代码 import axios, { AxiosInstance, AxiosRequestConfig } from 'axios' import { ElLoading } from 'element-plus' import { LoadingInstance } from 'element-plus/es/components/loading/src/loading' // 在代码中引用需要手动导入对应组件的样式 import 'element-plus/es/components/loading/style/css' // 添加自定义拦截器类型 interface MJRequestInterceptors { requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig requestInterceptorCatch?: (error: any) => any responseInterceptor?: (res: any) => any responseInterceptorCatch?: (error: any) => any } // 定义自己的类型 继承axios原始类型的同时集成自定义拦截器的类型 interface MJRequestConfig extends AxiosRequestConfig { interceptors?: MJRequestInterceptors showLoading?: boolean } const DEFAULT_LOADING = false class MJRequest { // 引入类型 private instance: AxiosInstance private interceptors?: MJRequestInterceptors private loading?: LoadingInstance private showLoading: boolean // 创建MJREsquest时候传入的选项 constructor(config: MJRequestConfig) { // 获取传入数据 this.instance = axios.create(config) this.interceptors = config.interceptors this.showLoading = config.showLoading ?? DEFAULT_LOADING // 单个实例独有的拦截器 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('All_Request_success') if (this.showLoading) { this.loading = ElLoading.service({ lock: true, text: '努力搬运中', background: 'rgba(0,0,0,0.5)' }) } return config }, (err) => { console.log('All_Request_error') return err } ) this.instance.interceptors.response.use( (res) => { console.log('All_Response_success') setTimeout(() => { this.loading?.close() }, 1000) switch (res.data.returnCode) { case '-1001': console.log('请求失败错误信息....') break // 以此类推... default: break } return res.data }, (err) => { console.log('All_Response_error') this.loading?.close() switch (err.response.status) { case 404: console.log('404错误...') break // 以此类推... default: break } return err } ) } // 调用请求发出请求 request<T>(config: MJRequestConfig): 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?.responseInterceptor) { res = config.interceptors.responseInterceptor(res) } // 重置loading this.showLoading = DEFAULT_LOADING // 返回res resolve(res) }) .catch((err) => { reject(err) // 重置loading this.showLoading = DEFAULT_LOADING }) }) } } export default MJRequest
获取Token请求
因为tonke是存放在Vuex中的所以我们应该去vuex中获取,但是现在还没有获取到Token所以先定义静态资源代替
公共属性配置
const token = ''
if (token) {
config.headers.Aunthorization = `Bearer ${token}`
}
封装请求方式
get<T = any>(config: AxiosRequestConfig): Promise<T> {
return this.request({ ...config, method: 'GET' })
}
post<T = any>(config: AxiosRequestConfig): Promise<T> {
return this.request({ ...config, method: 'POST' })
}
patch<T = any>(config: AxiosRequestConfig): Promise<T> {
return this.request({ ...config, method: 'PATCH' })
}
delete<T = any>(config: AxiosRequestConfig): Promise<T> {
return this.request({ ...config, method: 'DELETE' })
}
最终代码
核心代码
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { ElLoading } from 'element-plus'
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading'
// 在代码中引用需要手动导入对应组件的样式
import 'element-plus/es/components/loading/style/css'
// 添加自定义拦截器类型
interface MJRequestInterceptors<T = AxiosResponse> {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: any) => any
responseInterceptor?: (res: T) => T
responseInterceptorCatch?: (error: any) => any
}
// 定义自己的类型 继承axios原始类型的同时集成自定义拦截器的类型
interface MJRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: MJRequestInterceptors<T>
showLoading?: boolean
}
const DEFAULT_LOADING = true
class MJRequest {
// 引入类型
private instance: AxiosInstance
private interceptors?: MJRequestInterceptors
private loading?: LoadingInstance
private showLoading: boolean
// 创建MJREsquest时候传入的选项
constructor(config: MJRequestConfig) {
// 获取传入数据
this.instance = axios.create(config)
this.interceptors = config.interceptors
this.showLoading = config.showLoading ?? DEFAULT_LOADING
// 单个实例独有的拦截器
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('All_Request_success')
if (this.showLoading) {
this.loading = ElLoading.service({
lock: true,
text: '努力搬运中',
background: 'rgba(0,0,0,0.5)'
})
}
return config
},
(err) => {
// console.log('All_Request_error')
return err
}
)
this.instance.interceptors.response.use(
(res) => {
// console.log('All_Response_success')
setTimeout(() => {
this.loading?.close()
}, 1000)
switch (res.data.returnCode) {
case '-1001':
console.log('请求失败错误信息....')
break
// 以此类推...
default:
break
}
return res.data
},
(err) => {
// console.log('All_Response_error')
this.loading?.close()
switch (err.response.status) {
case 404:
console.log('404错误...')
break
// 以此类推...
default:
break
}
return err
}
)
}
// 调用请求发出请求
request<T>(config: MJRequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
// 获取数据
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
if (config.showLoading === false) {
this.showLoading = config.showLoading
}
this.instance
.request<any, T>(config)
.then((res) => {
// 单个请求的拦截器
if (config.interceptors?.responseInterceptor) {
res = config.interceptors.responseInterceptor(res)
}
// 重置loading
this.showLoading = DEFAULT_LOADING
// 返回res
resolve(res)
})
.catch((err) => {
reject(err)
// 重置loading
this.showLoading = DEFAULT_LOADING
})
})
}
get<T>(config: MJRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'GET' })
}
post<T>(config: MJRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'POST' })
}
delete<T>(config: MJRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'DELETE' })
}
patch<T>(config: MJRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'PATCH' })
}
}
export default MJRequest
公共属性配置
import MJRequest from './request'
const timeout = parseInt(process.env.VUE_APP_TIME_OUT || '1000')
const mjRequest = new MJRequest({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: timeout,
interceptors: {
requestInterceptor: (config) => {
console.log('请求成功的拦截')
// const token = ''
// if (token) {
// config.headers.Aunthorization = `Bearer ${token}`
// }
return config
},
// requestInterceptorCatch: (err) => {
// console.log('请求失败的拦截')
// return err
// },
responseInterceptor: (res) => {
console.log('响应成功的拦截')
return res
}
// responseInterceptorCatch: (err) => {
// console.log('响应失败的拦截')
// return err
// }
}
})
export default mjRequest
外部文件使用
// mjRequest.request({
// url: '/home/multidata',
// method: 'GET',
// interceptors: {
// requestInterceptor: (config) => {
// console.log('单独请求的config')
// return config
// },
// responseInterceptor: (res) => {
// console.log('单独响应的response')
// return res
// }
// }
// })
// mjRequest.request({
// url: '/home/multidata',
// method: 'GET',
// showLoading: true
// })
interface DataType {
data: any
returnCode: string
success: boolean
}
mjRequest
.get<DataType>({
url: '/home/multidata'
})
.then((res) => {
console.log(res.data)
console.log(res.returnCode)
console.log(res.success)
})
代码结构