const withRetry = async<T>(
fn: (signal?: AbortSignal) => Promise<T>
retries=3,
delay=1000,
params?: any,
signal?: AbortSignal,
) => {
try {
if(signal?.aborted) {
return {
status: 'networdError',
error: {
message: '请求已取消',
params
},
params,
};
}
const result = await fn(signal);
return {
status: 'success',
data: result,
params
};
}catch(error) {
if(signal?.aborted || retries < 0) {
const errorMsg = signal?.aborted ? '请求已取消'
: error?.message || '请求失败,已达最大重试次数';
return {
status: 'newworkError',
error: {
message: errorMsg,
code: error?.code,
retries: 3-retries,
params,
},
params,
}
}
const retryDelay = delay * Math.pow(2, 3 - retries);
await new Promise(resolve => setTimeout(resolve, retryDelay));
return withRetry(fn, retries-1, delay, params, signal);
}
};
const batchPromise = async <T>(
tasks: Array<() => Promise<T>>,
batchSize: number = 5
): Promise<T[]> => {
const results: T[] = [];
for(let i = 0; i< tasks.length; i += batchSize) {
const batch = tasks.slice(i, i + batchSize);
const batchResults = await Promise.allSettled(batch.map(task => task()));
batchResults.forEach(result => {
if(result.status === 'fulfilled') {
results.push(result.value);
}else {
console.log(result.reason);
}
});
}
return results;
}
const queryAllList = () => {
const controller = abortController || new AbortController();
const {signal} = controller;
const tasks = groups.map(item => {
return () => withRetry(
(reqSignal) => listApi({
params1: item.params1,
params2: item.params2,
signal: reqSignal
}).then(res => {
if(res.code === 200) {
return { ...res.data };
}else {
const error = new Error(`业务错误: ${res.msg || '未知错误'}`);
error.code = res.code;
throw error;
}
}),
3,
1000,
item,
signal
);
});
const results = await Promise.all(tasks);
const results = await batchPromise(tasks, 5);
return results.filter(Boolean);
}