优化
This commit is contained in:
89
client/shared/utils/request.ts
Normal file
89
client/shared/utils/request.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import _chunk from 'lodash/chunk';
|
||||
import _flatten from 'lodash/flatten';
|
||||
|
||||
interface QueueItem<T, R> {
|
||||
params: T;
|
||||
resolve: (r: R) => void;
|
||||
reject: (reason: unknown) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个自动合并请求的函数
|
||||
* 在一定窗口期内的所有请求都会被合并提交合并发送
|
||||
* @param fn 合并后的请求函数
|
||||
* @param windowMs 窗口期
|
||||
*/
|
||||
export function createAutoMergedRequest<T, R>(
|
||||
fn: (mergedParams: T[]) => Promise<R[]>,
|
||||
windowMs = 200
|
||||
): (params: T) => Promise<R> {
|
||||
let queue: QueueItem<T, R>[] = [];
|
||||
let timer: number | null = null;
|
||||
|
||||
async function submitQueue() {
|
||||
timer = null; // 清空计时器以接受后续请求
|
||||
const _queue = [...queue];
|
||||
queue = []; // 清空队列
|
||||
|
||||
try {
|
||||
const list = await fn(_queue.map((q) => q.params));
|
||||
_queue.forEach((q1, i) => {
|
||||
q1.resolve(list[i]);
|
||||
});
|
||||
} catch (err) {
|
||||
_queue.forEach((q2) => {
|
||||
q2.reject(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (params: T): Promise<R> => {
|
||||
if (!timer) {
|
||||
// 如果没有开始窗口期,则创建
|
||||
timer = window.setTimeout(() => {
|
||||
submitQueue();
|
||||
}, windowMs);
|
||||
}
|
||||
|
||||
return new Promise<R>((resolve, reject) => {
|
||||
queue.push({
|
||||
params,
|
||||
resolve,
|
||||
reject,
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个自动拆分请求参数的函数
|
||||
*/
|
||||
export function createAutoSplitRequest<Key, Item>(
|
||||
fn: (keys: Key[]) => Promise<Item[]>,
|
||||
type: 'serial' | 'parallel',
|
||||
limit = 100
|
||||
): (arr: Key[]) => Promise<Item[]> {
|
||||
return async (arr: Key[]): Promise<Item[]> => {
|
||||
const groups = _chunk(arr, limit);
|
||||
|
||||
if (type === 'serial') {
|
||||
const list: Item[] = [];
|
||||
for (const group of groups) {
|
||||
const res = await fn(group);
|
||||
if (Array.isArray(res)) {
|
||||
list.push(...res);
|
||||
} else {
|
||||
console.warn('[createAutoSplitRequest] fn should be return array');
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
} else if (type === 'parallel') {
|
||||
const res = await Promise.all(groups.map((group) => fn(group)));
|
||||
|
||||
return _flatten(res);
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user