1、封装
// @/types/index.ts
export interface MyResponseType<T = any> {
code: number;
message: string;
data: T;
}
// @/utils/request.ts
import axios, { AxiosRequestConfig } from 'axios'
import { MyResponseType } from '@/types'
const instance = axios.create({
baseURL: '/api'
})
const request = async <T = any>(config: AxiosRequestConfig): Promise<MyResponseType<T>> => {
try {
const { data } = await instance.request<MyResponseType<T>>(config)
data.code === 0
? console.log(data.message) // 成功消息提示
: console.error(data.message) // 失败消息提示
return data
} catch (err) {
const message = err.message || '请求失败'
console.error(message) // 失败消息提示
return {
code: -1,
message,
data: null as any
}
}
}
1、使用
// @/types/index.ts
export interface User {
name: string;
}
// @/api/test.ts
import { User } from '@/types'
import request from '@/utils/request'
export const successApi = () => {
return request<User>({
url: '/success',
method: 'get'
})
}
export const failApi = () => {
return request<User>({
url: '/fail',
method: 'get'
})
}
2、类的封装
ts封装
service/request/types.ts
import type {
AxiosResponse,
InternalAxiosRequestConfig,
CreateAxiosDefaults,
AxiosRequestConfig,
} from 'axios'
export interface RequestInterceptors<T> {
// 请求拦截
requestInterceptors?: (
config: InternalAxiosRequestConfig,
) => InternalAxiosRequestConfig
requestInterceptorsCatch?: (err: any) => any
// 响应拦截
responseInterceptors?: (config: T) => T
responseInterceptorsCatch?: (err: any) => any
}
// 自定义传入的参数
export interface CreateRequestConfig<T = AxiosResponse>
extends CreateAxiosDefaults {
interceptors?: RequestInterceptors<T>
}
export interface RequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: RequestInterceptors<T>
}
export interface CancelRequestSource {
[index: string]: () => void
}
class封装
service/request/index.ts
import axios, { AxiosResponse } from 'axios'
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios'
import type {
RequestConfig,
RequestInterceptors,
CreateRequestConfig,
} from './types'
class Request {
// axios 实例
instance: AxiosInstance
// 拦截器对象
interceptorsObj?: RequestInterceptors<AxiosResponse>
// * 存放取消请求控制器Map
abortControllerMap: Map<string, AbortController>
constructor(config: CreateRequestConfig) {
this.instance = axios.create(config)
// * 初始化存放取消请求控制器Map
this.abortControllerMap = new Map()
this.interceptorsObj = config.interceptors
// 拦截器执行顺序 接口请求 -> 实例请求 -> 全局请求 -> 实例响应 -> 全局响应 -> 接口响应
this.instance.interceptors.request.use(
(res: InternalAxiosRequestConfig) => {
const controller = new AbortController()
const url = res.url || ''
res.signal = controller.signal
this.abortControllerMap.set(url, controller)
return res
},
(err: any) => err,
)
// 使用实例拦截器
this.instance.interceptors.request.use(
this.interceptorsObj?.requestInterceptors,
this.interceptorsObj?.requestInterceptorsCatch,
)
this.instance.interceptors.response.use(
this.interceptorsObj?.responseInterceptors,
this.interceptorsObj?.responseInterceptorsCatch,
)
// 全局响应拦截器保证最后执行
this.instance.interceptors.response.use(
// 因为我们接口的数据都在res.data下,所以我们直接返回res.data
(res: AxiosResponse) => {
const url = res.config.url || ''
this.abortControllerMap.delete(url)
return res.data
},
(err: any) => err,
)
}
request<T>(config: RequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
// 如果我们为单个请求设置拦截器,这里使用单个请求的拦截器
if (config.interceptors?.requestInterceptors) {
config = config.interceptors.requestInterceptors(config as any)
}
this.instance
.request<any, T>(config)
.then(res => {
// 如果我们为单个响应设置拦截器,这里使用单个响应的拦截器
if (config.interceptors?.responseInterceptors) {
res = config.interceptors.responseInterceptors(res)
}
resolve(res)
})
.catch((err: any) => {
reject(err)
})
// .finally(() => {})
})
}
/**
* 取消全部请求
*/
cancelAllRequest() {
for (const [, controller] of this.abortControllerMap) {
controller.abort()
}
this.abortControllerMap.clear()
}
/**
* 取消指定的请求
* @param url 待取消的请求URL
*/
cancelRequest(url: string | string[]) {
const urlList = Array.isArray(url) ? url : [url]
for (const _url of urlList) {
this.abortControllerMap.get(_url)?.abort()
this.abortControllerMap.delete(_url)
}
}
}
export default Request
export { RequestConfig, RequestInterceptors }
发起请求
service/index.ts
import Request from './request'
import { AxiosResponse } from 'axios'
import type { RequestConfig } from './request/types'
export interface YWZResponse<T> {
statusCode: number
desc: string
result: T
}
// 重写返回类型
interface YWZRequestConfig<T, R> extends RequestConfig<YWZResponse<R>> {
data?: T
}
const request = new Request({
baseURL: import.meta.env.BASE_URL,
timeout: 1000 * 60 * 5,
interceptors: {
// 请求拦截器
requestInterceptors: config => config,
// 响应拦截器
responseInterceptors: (result: AxiosResponse) => {
return result
},
},
})
/**
* @description: 函数的描述
* @generic D 请求参数
* @generic T 响应结构
* @param {YWZRequestConfig} config 不管是GET还是POST请求都使用data
* @returns {Promise}
*/
const ywzRequest = <D = any, T = any>(config: YWZRequestConfig<D, T>) => {
const { method = 'GET' } = config
if (method === 'get' || method === 'GET') {
config.params = config.data
}
return request.request<YWZResponse<T>>(config)
}
// // 取消请求
// export const cancelRequest = (url: string | string[]) => {
// return request.cancelRequest(url)
// }
// // 取消全部请求
// export const cancelAllRequest = () => {
// return request.cancelAllRequest()
// }
export default ywzRequest