关于axios重复请求的问题

关于axios重复请求的问题

class版本

request.ts

import axios, { InternalAxiosRequestConfig } from 'axios';

import axiosCancel from './axiosCancelClass';


const instance = axios.create({
	baseURL: 'http://localhost:8889/',
	// baseURL: 'https://localhost:3000',
	timeout: 10 * 1000,
});
instance.interceptors.request.use(
	config => {
		axiosCancel.pushCancel(config);
		return config;
	},
	error => {
		if (error.config) {
			axiosCancel.deleteCancel(error.config);
		}
		// 对请求错误做些什么
		return Promise.reject(error);
	},
);

instance.interceptors.response.use(
	config => {
		axiosCancel.deleteCancel(config.config);
		return config;
	},
	error => {
		if (error.config) {
			axiosCancel.deleteCancel(error.config);
		}
		// 对请求错误做些什么
		return new Promise(() => {});
	},
);
export default instance;

axiosCancel.ts

import axios, { InternalAxiosRequestConfig } from 'axios';
type CancelAllAxios = {
	all?: boolean;
	config?: Option | Option[];
};
type Option = {
	url?: string;
	method: string;
	reg?: RegExp;
};
type WhiteList = Option[];
type Config = {
	url: string;
	method: string;
};

class axiosCancel {
	whiteList: WhiteList;
	#Mapping: Map<string, Function>;
	constructor() {
		this.whiteList = [];
		this.#Mapping = new Map();
	}
	#cancelAxiosSingle(config: InternalAxiosRequestConfig): void {
		let key = this.#getMapKey(config);
		let cancel = this.#Mapping.get(key);
		cancel && cancel();
	}
	#isIncludes(arr: WhiteList, config: Config): boolean {
		let urls = arr.filter(item => {
			if (
				item.url &&
				Object.prototype.toString.call(item.url) === '[object String]'
			) {
				let result =
					(item.url as string) === config.url &&
					item.method.toLowerCase() === config.method.toLowerCase();
				return result;
			}
			if (
				item.reg &&
				Object.prototype.toString.call(item.reg) === '[object RegExp]'
			) {
				let result =
					(item.reg as RegExp).test(config.url as string) &&
					item.method.toLowerCase() === config.method.toLowerCase();

				return result;
			}
			return false;
		});

		return urls.length > 0;
	}
	#getMapKey(config: InternalAxiosRequestConfig): string {
		const key = `${config?.url}&${config?.method?.toLowerCase()}`;
		return key;
	}
	#addCancel(config: InternalAxiosRequestConfig): void {
		config.cancelToken =
			config.cancelToken ??
			new axios.CancelToken(cancel => {
				this.#Mapping.set(this.#getMapKey(config), cancel);
			});
	}
	pushCancel(config: InternalAxiosRequestConfig): void {
		if (this.#isIncludes(this.whiteList, config as Config)) {
			return;
		}

		let isCancelBefore: boolean =
			config?.data?.cancelBefore ?? config?.params?.cancelBefore ?? true;

		if (config?.data) {
			config.data && Reflect.deleteProperty(config.data, 'cancelBefore');
		} else {
			config.params &&
				Reflect.deleteProperty(config.params, 'cancelBefore');
		}
		let key = this.#getMapKey(config);

		if (isCancelBefore) {
			if (this.#Mapping.has(key)) {
				this.#cancelAxiosSingle(config);
				this.deleteCancel(config);
			}
			this.#addCancel(config);
		} else {
			if (this.#Mapping.has(key)) {
				config.cancelToken = new axios.CancelToken(cancel => {
					cancel();
				});
			} else {
				this.#addCancel(config);
			}
		}
	}

	deleteCancel(config: InternalAxiosRequestConfig): void {
		let key = this.#getMapKey(config);
		this.#Mapping.delete(key);
	}

	cancelAxios(config: CancelAllAxios): Promise<void> {
		for (const [key, cancel] of this.#Mapping) {
			let [url, method] = key.split('&');
			let currentConfig = {
				url,
				method,
			};
			if (config.all === true) {
				cancel('');
				this.#Mapping.delete(key);
			} else {
				if (
					Object.prototype.toString.call(config.config) ===
					'[object Array]'
				) {
					if (
						this.#isIncludes(
							config.config as Option[],
							currentConfig,
						)
					) {
						cancel('');
						this.#Mapping.delete(key);
					}
				} else if (
					Object.prototype.toString.call(config.config) ===
					'[object Object]'
				) {
					if (
						this.#isIncludes(
							[config.config] as Option[],
							currentConfig,
						)
					) {
						cancel('');
						this.#Mapping.delete(key);
					}
				}
			}
		}
		return Promise.resolve();
	}
}
let AxiosCancel = new axiosCancel();
export default AxiosCancel;

/**
 * @desc //TODO AxiosCancel.cancelAxios()
 * //* 只会取消非白名单外的请求,参数为两个,all:是否取消所有请求,适合炉头跳转前调用,但记得先将字典加入白名单
 * //*    		 					   url:字符串时取消单个,数组时取消多个
 * @desc //TODO whiteList
 * //* 白名单:白名单里的url会跳过,不接受处理和取消
 * @desc //TODO cancelBefore
 * //* 写在data或params里,默认为true,true:维持最新一条请求
 * //*					 			false:维持第一条请求
 */



index.vue


	axiosCancel.whiteList.push({
		url: '/api/plice',
		method: 'post',
	});
	axiosCancel.whiteList.push({
		method: 'get',
		reg: /\/api\/plice/,
	});
	const cancel = (): void => {
		axiosCancel.cancelAxios({
			all: true,
		});
	};
	const cancel = (): void => {
		axiosCancel.cancelAxios({
			config: {
				method: 'get',
				url: '/api/plice',
			},
		});
	};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值