import axios from 'axios' import type { CancelTokenStatic, AxiosRequestConfig, AxiosInstance, AxiosError, InternalAxiosRequestConfig, AxiosResponse, CancelTokenSource } from 'axios' import { useGlobalStore } from '@/stores' import { hasOwn, hasOwnDefault } from '@/utils' import { ElMessage } from 'element-plus' /** * @description: 请求配置 * @param {extendHeaders} {[key: string]: string} 扩展请求头用于不满足默认的 Content-Type、token 请求头的情况 * @param {ignoreLoading} boolean 是否忽略 loading 默认 false * @param {token} boolean 是否携带 token 默认 true * @param {ignoreCR} boolean 是否取消请求 默认 false * @param {ignoreCRMsg} string 取消请求的提示信息 默认 Request canceled * @param {contentType} $ContentType 重新定义 Content-Type 默认 json * @param {baseURL} $baseURL baseURL 默认 horizon * @param {timeout} number 超时时间 默认 10000 * @return {_AxiosRequestConfig} **/ interface _AxiosRequestConfig extends AxiosRequestConfig { extendHeaders?: { [key: string]: string } ignoreLoading?: boolean token?: boolean ignoreCR?: boolean ignoreCRMsg?: string } enum ContentType { html = 'text/html', text = 'text/plain', file = 'multipart/form-data', json = 'application/json', form = 'application/x-www-form-urlencoded', stream = 'application/octet-stream', } const Request: AxiosInstance = axios.create() const CancelToken: CancelTokenStatic = axios.CancelToken const source: CancelTokenSource = CancelToken.source() const globalStore = useGlobalStore() Request.interceptors.request.use( (config: InternalAxiosRequestConfig) => { globalStore.setGlobalState('loading', !hasOwnDefault(config, 'ignoreLoading', true)) config.baseURL = hasOwnDefault(config, 'baseURL', '/api') config.headers = { ...config.headers, ...{ 'Content-Type': ContentType[hasOwnDefault(config, 'Content-Type', 'json')], }, ...hasOwnDefault(config, 'extendHeaders', {}), } hasOwnDefault(config, 'token', true) && (config.headers.token = globalStore.token) config.data = config.data || {} config.params = config.params || {} config.timeout = hasOwnDefault(config, 'timeout', 10000) config.cancelToken = source.token config.withCredentials = true hasOwnDefault(config, 'ignoreCR', false) && source.cancel(hasOwnDefault(config, 'ignoreCRMsg', 'Request canceled')) return config }, (error: AxiosError) => { return Promise.reject(error) } ) Request.interceptors.response.use( (response: AxiosResponse) => { globalStore.setGlobalState('loading', false) const { data, status } = response let obj = { ...data } if (!hasOwn(data, 'status')) obj.status = status return obj }, (error: AxiosError) => { globalStore.setGlobalState('loading', false) ElMessage.error(error.message) return Promise.reject(error) } ) export default (config?: _AxiosRequestConfig) => Request(config) 修改代码,使其能够批量取消请求, 并给出例子
时间: 2024-01-06 14:04:13 浏览: 228
修改后的代码如下:
```typescript
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelTokenStatic } from 'axios';
import { useGlobalStore } from '@/stores';
import { hasOwn, hasOwnDefault } from '@/utils';
import { ElMessage } from 'element-plus';
interface _AxiosRequestConfig extends AxiosRequestConfig {
extendHeaders?: { [key: string]: string };
ignoreLoading?: boolean;
token?: boolean;
ignoreCR?: boolean;
ignoreCRMsg?: string;
}
enum ContentType {
html = 'text/html',
text = 'text/plain',
file = 'multipart/form-data',
json = 'application/json',
form = 'application/x-www-form-urlencoded',
stream = 'application/octet-stream',
}
interface PendingRequest {
url?: string;
cancel: () => void;
}
const Request: AxiosInstance = axios.create();
const CancelToken: CancelTokenStatic = axios.CancelToken;
const pendingRequests: Map<string, PendingRequest> = new Map();
const globalStore = useGlobalStore();
Request.interceptors.request.use(
(config: _AxiosRequestConfig) => {
globalStore.setGlobalState('loading', !hasOwnDefault(config, 'ignoreLoading', true));
config.baseURL = hasOwnDefault(config, 'baseURL', '/api');
config.headers = {
...config.headers,
...{ 'Content-Type': ContentType[hasOwnDefault(config, 'Content-Type', 'json')] },
...hasOwnDefault(config, 'extendHeaders', {}),
};
hasOwnDefault(config, 'token', true) && (config.headers.token = globalStore.token);
config.data = config.data || {};
config.params = config.params || {};
config.timeout = hasOwnDefault(config, 'timeout', 10000);
config.cancelToken =
config.cancelToken ||
new CancelToken((cancel) => {
const url = config.url || '';
if (!pendingRequests.has(url)) {
pendingRequests.set(url, { cancel });
}
});
config.withCredentials = true;
hasOwnDefault(config, 'ignoreCR', false) &&
config.cancelToken!.throwIfRequested() &&
config.cancelToken!.promise.catch((reason) => {
ElMessage.warning(hasOwnDefault(config, 'ignoreCRMsg', 'Request canceled'));
throw reason;
});
return config;
},
(error) => {
return Promise.reject(error);
}
);
Request.interceptors.response.use(
(response: AxiosResponse) => {
globalStore.setGlobalState('loading', false);
const { data, status } = response;
let obj = { ...data };
if (!hasOwn(data, 'status')) obj.status = status;
const url = response.config.url || '';
pendingRequests.delete(url);
return obj;
},
(error) => {
globalStore.setGlobalState('loading', false);
const url = error.config.url || '';
const pendingRequest = pendingRequests.get(url);
if (pendingRequest) {
pendingRequest.cancel();
pendingRequests.delete(url);
}
ElMessage.error(error.message);
return Promise.reject(error);
}
);
export default (config?: _AxiosRequestConfig) => Request(config);
```
需要注意的是,我们使用了一个 Map 存储待处理的请求,在请求发起时将其加入 Map,然后在响应拦截器中将其删除。在请求错误时,如果当前请求在 Map 中,则取消该请求并从 Map 中删除。这样就可以批量取消请求了。
以下是一个取消请求的例子:
```typescript
import api from '@/api';
const CancelToken = api.CancelToken;
// 模拟多个请求
const request1 = api.get('/api/user/1', { cancelToken: new CancelToken((c) => (cancel1 = c)) });
const request2 = api.get('/api/user/2', { cancelToken: new CancelToken((c) => (cancel2 = c)) });
const request3 = api.get('/api/user/3', { cancelToken: new CancelToken((c) => (cancel3 = c)) });
// 取消第一个请求
let cancel1;
cancel1();
// 批量取消
let cancelAll;
Promise.all([request1, request2, request3])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
})
.finally(() => {
cancelAll && cancelAll();
});
// 取消所有请求
cancelAll = () => {
api.cancelAll();
};
```
阅读全文