TkAstral3D/packages/sdk/lib/utils/request/fetchController.ts
2025-10-04 23:36:07 +08:00

75 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 创建一个handlerFetch
*
* @param limit 并发控制
* @param timeout 超时设
* @return function 返回一个函数
*/
export function fetchController(limit: number, timeout: number | boolean) {
limit = limit || 1;
timeout = timeout || false;
let count = 0, pool: any = [];
return function (url: string, options?: any) {
// 通过AbortController 控制 取消fetch 请求
let controller = new AbortController();
let signal = controller.signal;
// 判断是否需要超时
let isTimeout = options && options.timeout || timeout;
// 控制请求超时
let timeoutPromise = () => {
return new Promise((reject) => {
setTimeout(() => {
// resolve('请求超时');
reject('请求超时');
controller.abort();
}, options?.timeout || timeout)
})
}
// 返回fetch 本身
let taskPromise = () => new Promise((resolve, reject) => {
fetch(url, { signal, ...options }).then(res => {
resolve(res);
}).catch(err => {
reject(err)
})
});
// 通过Promise.race可以控制超时并在访问结果中 去继续调用等待池中的请求
let task = () => (isTimeout ? Promise.race([timeoutPromise(), taskPromise()]) : taskPromise())
.then((res) => {
options.onSuccess && options.onSuccess(res)
next();
})
.catch((err) => {
options.onError && options.onError(err)
next();
});
// 定一个next 控制等待队列中的请求继续并发调用
let next = () => {
// 每执行一次next count - 1然后比较当前的count 与 limit
// 如果小于limit 循环执行limit-count 次
count--;
if (count < limit && pool.length) {
let n = limit - count;
for (let i = 0; i < n; i++) {
let curTask: any = pool.shift();
curTask();
++count;
}
}
};
// 比较count与limit 大于等于limit的推入等待队列 小于limit的 count + 1并执行fetch请求
if (count >= limit) {
pool.push(task);
} else {
++count;
task();
}
}
}