首页 > 其他分享 >使用 async-await 实现一个请求失败自动重新请求的函数

使用 async-await 实现一个请求失败自动重新请求的函数

时间:2022-08-31 11:37:43浏览次数:76  
标签:resolve return 请求 exec await timeId Promise timeout async

在项目开发中, 需要拉取 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

相关文章