一、目的
防止短时间内同一接口未响应,再次发起请求
二、代码实现
1、定义类型
// 响应的结果
interface IResponse<T>{
code: number,
error: string,
result: T
}
interface IUrlConfig {
url: string,
method: 'get' | 'post' | 'delete' | 'put'
}
interface IRequestConfig {
[key: string]: IUrlConfig
}
interface IConfig {
// 请求参数
data?: any,
// 请求结果的处理器
handler?: any
}
2、实现一次封装
封装请求拦截器和响应拦截器
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
class Axios {
static instance: AxiosInstance | undefined = undefined
protected constructor() { }
static createInstance(): AxiosInstance {
let instance = Axios.instance || axios.create({
baseURL: '',
timeout: 5000
})
// 请求拦截器
this.requestInterceptors(instance)
// 响应拦截器
this.responseInterceptors(instance)
return instance
}
// 请求拦截器
protected static requestInterceptors(instance: AxiosInstance) {
instance.interceptors.request.use((config: AxiosRequestConfig) => {
// 配置token
config.headers!['token'] = 'token'
return config
}, error => {
Promise.reject(error)
})
}
// 响应拦截器
protected static responseInterceptors(instance: AxiosInstance) {
instance.interceptors.response.use((response: AxiosResponse<IResponse<any>>) => {
if (response.data.code === 401) {
console.log('处理401事情')
}
return response.data
}, error => {
Promise.reject(error)
})
}
}
export default Axios.createInstance()
3、实现二次封装
封装请求的对象
// 导入一次封装中的axios实例
import { AxiosResponse } from 'axios';
import axios from './Axios';
class AxiosServer {
[key: string]: { [key: string]: any }
constructor() { }
// 设置请求属性 requestConfig login: { url: 'api/puglic/login', method: 'post' }
// 设置属性后,最终请求方式是 api.public.login() api就是AxiosServer的实例
setOptions(moduleName: string, requestConfig: IRequestConfig): void {
Object.keys(requestConfig).forEach(key => {
this[moduleName][key] = this.request.bind(this, moduleName, key, requestConfig[key])
// 设置锁
this[moduleName][key].state = 'unlocked'
})
}
// 请求
request<T>(moduleName: string, requestName: string, urlConfig: IUrlConfig, config: IConfig): Promise<IResponse<T>> {
const method = urlConfig.method || 'get'
const url = urlConfig.url
const params = config.data
const ctx = this
return new Promise((resolve, reject) => {
// 默认处理响应结果的处理方法
const defaultHandler = (response: IResponse<T>) => {
resolve(response)
}
// 如果没有传自定义的 handler就使用默认的handler
const handler = config.handler || defaultHandler
// 请求后的回调
const callback = (response: AxiosResponse<IResponse<T>>) => {
// 请求已经响应, 解除当前请求的锁
ctx[moduleName][requestName].state = 'unlocked'
handler(response)
}
// 发起请求
const request: { [key: string]: Function } = {
get: () => {
axios.get(url, { params }).then(callback)
},
post: () => {
axios.post(url, params).then(callback)
},
delete: () => {
axios.delete(url, { params }).then(callback)
},
put: () => {
axios.put(url, { params }).then(callback)
}
}
// 判断当前的请求是否未锁
if (ctx[moduleName][requestName].state === 'unlocked') {
// 开始请求,将当前接口锁住
ctx[moduleName][requestName].state = 'locked'
if (request[method]) {
request[method]()
} else {
reject(new Error('无效的请求类型'))
}
}
})
}
}
export default new AxiosServer()
4、配置请求
public模块的配置
// public模块的请求配置
const apis: IRequestConfig = {
login: { url: '/api/public/login', method: 'post' },
logout: { url: '/api/public/logout', method: 'delete' }
}
export default apis
business模块的配置
const apis: IHttpUrlConfig = {
notes: { url: '/api/business/notes', method: 'get' }
}
export default apis
5、设置配置项
// 导入二次封装的AxiosServer实例
import server from '../utils/axios'
// 导入配置
import pub from './public'
import business from './business'
server.setOptions('public', pub)
server.setOptions('business', business)
export default server
// 最终的使用方式是 在需要请求的页面中 导入server
// 请求案例
// api就是导出的server
import api from './server'
api.public.login()
api.public.logout()
api.business.notes()
// 传参的请求方式
api.public.login({ data: { usercode: 'admin', userpwd: '123' }})
// 自定义处理请求的handler
api.business.notes({ handler: (response)=>{
console.log(response)
}})
// 返回结果类型传入
interfance INote {
note_id: number,
note_content: string
}
api.business.notes<INote[]>()
三、结语
以上就是关于axios二次封装最简单的应用,防止短时间内同一个请求未响应,再次发起请求,这只是简单思路,如有不正确的地方,请及时指正。