不知道大家有没有遇到这种场景,在上传文件分片的时候很多分片一起上传,导致浏览器对单个域名的请求过多其他的请求全都挂起了,页面直接其他请求无响应但是 页面又不可以刷新。这个时候要是能有一个工具帮我们发送请求并且控制并发数量的话就不会有这个限制了,并且还能够失败重试。或者是在一个列表上单个位置可能需要请求多个相同的接口,其实可以等待之前的接口结束直接使用,但是需要做的判断就比较多,不如我直接在这个接口返回数据的过程中丢弃其他相同的请求只用等待这一个。
在多个不同请求的时候需要限制并发数量使用 asyncQueue
在多个参数相同请求且几乎同一时刻发出的时候需要做到合并,使用MergeAsync
这是一个用于解决异步任务数量太大需要限制异步任务数量的库
,比如浏览器端 一次性发送很多的请求会导致请求挂起,例如在有大量图片加载时 网络不太好会导致后续其他的接口请求挂起得不到反馈,这时需要一个工具来解决同时请求图片的数量不得大于某个值,这样后续的接口请求才能正常的发送。于是此库便诞生了
npm i await-num-q
# or
pnpm i await-num-q
# or
yarn i await-num-q
导入
import { asyncQueue, MergeAsync } from 'await-num-q'
初始化队列
/**
*
* 异步参数对象
* @property max 最大并发数
* @property retry 失败重试次数
* @property endCallback 队列结束回调函数
*/
// export type AsyncParams = {
// max?: number;
// retry?: number;
// endCallback?: () => void;
// };
// 所有任务完成的回调
function endCallback() {}
// 最大并发数量
const max = 3
// 失败重试次数
const retry = 3
let q = new asyncQueue(max,retry,endCallback)
执行
async function test(){
async function _get(){}
// 可以把请求推进去但是不直接执行
// q.push(_get)
// q.run()
// 若是想直接执行
// q.run(_get, data => {}, err => {})
// ----------------------
// 但是 一般直接使用下面这种方式 这个函数是对上面的封装
let data = await q.wait(_get) // 这样就能拿到请求的数据 且不会超过指定数量
}
test()
// 合并多个请求
async function test2(){
// 该函数模拟多个请求
// 这里被包装的是某个接口
}
// 模拟多个位置 需要使用这个请求
for(let i = 0; i < 10; i++){
await MergeAsync(test2,"请求用的参数或者是唯一的key")
}
/**
* 异步参数对象
* @property max 最大并发数
* @property retry 失败重试次数
* @property endCallback 队列结束回调函数
*/
export type AsyncParams = {
max?: number;
retry?: number;
endCallback?: () => void;
};
export type RunFun = (...args: any) => Promise<any>;
/**
* 异步任务对象
*/
export interface RunFunBoj<T extends RunFun = () => Promise<any>> {
status: "wait" | "ing" | "end" | "fail";
target: T;
retry: number;
callback?: <D>(data: D) => void;
err?: (e: any) => void;
}
/**
* 异步队列
*/
export declare class asyncQueue {
#private;
constructor({ max, retry, endCallback, }: AsyncParams);
/**
* 添加任务
* @param f 目标函数
* @param callback 成功回调函数
* @param err 错误回调函数
* @returns 添加成功与否
*/
push<T extends RunFun>(f: T, callback?: <D>(data: D) => void, err?: (e: any) => void): boolean;
/**
* 清除运行完成的任务
*/
clear(fial?: boolean): void;
/**
* 添加并运行任务 若是没有传入函数 运行 之前传入的任务
* @param f 目标函数
* @param callback 成功回调函数
* @param err 错误回调函数
* @returns 添加成功与否
*/
run<T extends RunFun>(f?: T, callback?: <D>(data: D) => void, err?: (e: any) => void): Promise<void>;
get status(): "ing" | "end";
/**
* 获取所有的 任务
* @returns
*/
getTasks(): RunFunBoj<() => Promise<any>>[];
/**
* 异步运行并得到返回值
* @param fun 目标函数
* @returns
*/
wait<T extends RunFun>(fun: T): Promise<ReturnType<T>>;
}
/**
* 在某个异步请求 参数相同 返回的值相同
* 并且在同一时间段 会发送多个亲求的场景
* 压缩正在进行的异步请求 为一个
* 避免同时条用多个请求导致后续请求 挂起
* @param asyncFun 异步函数
* @param param 函数传参 必须传入支持序列化的
* @returns
*/
export declare function MergeAsync<T extends RunFun>(asyncFun: T, ...param: Parameters<T>): Promise<ReturnType<T>>;
喜欢的话给个star吧