mirror of https://github.com/msgbyte/tailchat
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
55 lines
1.2 KiB
TypeScript
55 lines
1.2 KiB
TypeScript
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 = []; // 清空队列
|
|
const ret = fn(_queue.map((q) => q.params));
|
|
|
|
try {
|
|
const list = await ret;
|
|
_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,
|
|
});
|
|
});
|
|
};
|
|
}
|