在项目开发中, 需要拉取 GA 数据放到自己的数据库中, 用于做更定制化的数据分析和图表等.
但是因为数据较多, GA 一次性只能取得 10w 条数据, 所以需要多次请求才能获取到完整的数据.又因为网络有时波动较大, 在后续的定时任务中可能会出现请求失败的情况.
所以需要一个在请求失败时自动重试的函数.
直接看代码:
// *请求失败时将重新尝试
export async function tryAgain<T extends Promise<any>>(
fn: () => T,
count: number = 3, // 重试次数
timeout: number = 5000 // 重试的延迟
): Promise<T> {
let tryCount = 1;
let timeId: NodeJS.Timeout;
const exec = async (): Promise<T> => {
const res: T | null = await fn().catch((err) => {
if (tryCount > count) {
throw err;
} else {
console.log(`request failed, trying re-request ${tryCount++} \n err:${err}`);
// 这里也可以直接返回 err 但是下面的判断条件下需要修改, 比如 if(res instanceof Error)
return null;
}
});
if (timeId) clearTimeout(timeId);
if (res) return res;
else {
if (timeout) {
/**
* 这里的 Promise 只是单纯的等待计时器完成, 不知道这样会不会不好
* 这里也可以直接把 exec 放到 resolve 里面. 大概是下面这样.
* 但是会将 Promise 修改为 fulfilled 虽然 exec 报错了将会抛出错误, 也可以正常使用
* 但是我有点小强迫症, 不喜欢这样.
* return new Promise((resolve) => {
* timeId = setTimeout(() => {
* resolve(exec())
* }, timeout)
* })
*/
await new Promise((resolve) => {
timeId = setTimeout(() => {
resolve("timeout");
}, timeout);
});
}
// *递归 + 尾调用
return exec();
}
};
return exec();
}
标签:resolve,return,请求,exec,await,timeId,Promise,timeout,async
From: https://www.cnblogs.com/99xx/p/re-request-function.html