import { IRequestOptions } from '../intf/IRequestOptions' interface IRequestCacheOptions { oMethod: Function salf: any request: IRequestOptions callback: { resolve: Function; reject: Function } } const cache: { max: number execute: number waitTask: Array } = { max: 0, execute: 0, waitTask: [] } /** 转化max值 */ const transformMaxVal = (max: any): number => { if (Number.isInteger(max) && max > 0) return max return 0 } /** 执行请求 */ const execute = async (options: IRequestCacheOptions) => { const { oMethod, salf, request, callback } = options // ? 并发数超过上限, 中断, 并存入缓存 if (cache.execute >= cache.max) { cache.waitTask.push(options) return } try { // 执行数 +1 cache.execute++ // 执行 const res = await oMethod.call(salf, request) // 回调 callback.resolve(res) } catch (error) { // 回调 callback.reject(error) } finally { // 执行数 -1 cache.execute-- // ? 如果存在等待中的请求, 那么拉出一个执行 // ? 如果, 执行时恰好进来一个请求, 那么, 这个请求又会重新排队. if (cache.waitTask.length > 0) { const task = cache.waitTask.shift() if (task) execute(task) } } } /** 处理请求最大并发 * * @description 注意: 全局公用同一缓存对象, 可能会在多实例场景下出现出现设定场景之外的问题 */ export const max = () => { return function (_target: any, _methodName: any, desc: any) { // 1. 保存当前的方法 const oMethod = desc.value // 2. 改写方法 desc.value = async function (req: IRequestOptions) { const salf = this const { max } = this.axios.defaults const maxVal: number = transformMaxVal(max) // 如果功能未开启, 则跳过当前方法 if (!maxVal) return await oMethod.apply(this, [req]) // 通过递归方式, 每次运行执行最大数量的请求 return new Promise((resolve, reject) => { const reqObj: IRequestCacheOptions = { oMethod, salf, request: req, callback: { resolve, reject } } // 每次接受请求时, 更新同时允许最大请求并发数 cache.max = maxVal // 执行 execute(reqObj) }) } } }