| import axios from 'axios'; |
| import type { InternalAxiosRequestConfig, AxiosRequestConfig, Canceler, AxiosResponse } from 'axios'; |
| |
| interface CustomRequestConfig extends AxiosRequestConfig { |
| debounce?: number; |
| } |
| |
| const pendingRequests = new Map<string, Canceler>(); |
| |
| |
| function getRequestKey(config: InternalAxiosRequestConfig) { |
| const { method, url, params, data } = config; |
| return [method, url, JSON.stringify(params), JSON.stringify(data)].join('&'); |
| } |
| |
| function addPendingRequest(config: InternalAxiosRequestConfig) { |
| const key = getRequestKey(config); |
| config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => { |
| if (!pendingRequests.has(key)) { |
| pendingRequests.set(key, cancel); |
| } |
| }) |
| } |
| |
| function removePendingRequest(config: InternalAxiosRequestConfig) { |
| const requestKey = getRequestKey(config); |
| if (pendingRequests.has(requestKey)) { |
| const cancel = pendingRequests.get(requestKey) as Canceler; |
| cancel(`取消重复请求: ${requestKey}`); |
| pendingRequests.delete(requestKey); |
| } |
| } |
| |
| export const service = axios.create({ |
| baseURL: '/', |
| timeout: 10000, |
| }) |
| |
| service.interceptors.request.use( |
| (config: InternalAxiosRequestConfig) => { |
| removePendingRequest(config); |
| addPendingRequest(config); |
| return config; |
| }, |
| error => { |
| return Promise.reject(error); |
| } |
| ) |
| |
| service.interceptors.response.use( |
| (response: AxiosResponse) => { |
| removePendingRequest(response.config); |
| return response.data; |
| }, |
| error => { |
| if (error.config) { |
| removePendingRequest(error.config); |
| } |
| |
| if (axios.isCancel(error)) { |
| console.log('请求已取消:', error.message); |
| } else { |
| console.error('请求发生错误:', error.message); |
| } |
| |
| return Promise.reject(error); |
| } |
| ) |
| |
| let debounceTimer: ReturnType<typeof setTimeout>; |
| |
| function debounceRequest<T> ( |
| func: (config: CustomRequestConfig) => Promise<T>, |
| delay: number |
| ): (config: CustomRequestConfig) => Promise<T> { |
| return function (config: CustomRequestConfig) { |
| clearTimeout(debounceTimer); |
| return new Promise((resolve, reject) => { |
| debounceTimer = setTimeout(() => { |
| console.log('qwer'); |
| func(config).then(resolve).catch(reject); |
| }, delay); |
| }) |
| } |
| } |
| |
| |
| function request<T = unknown>(options: CustomRequestConfig): Promise<T> { |
| if (options.debounce) { |
| return debounceRequest(config => service.request(config), options.debounce)(options) as Promise<T>; |
| } |
| return service.request(options); |
| } |
| |
| export default request; |