75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
/**
|
|
* 创建一个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();
|
|
}
|
|
}
|
|
}
|