Skip to content

Instantly share code, notes, and snippets.

@shrekuu
Last active February 5, 2023 15:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shrekuu/b92b9fb4ae5341050587e52221e56095 to your computer and use it in GitHub Desktop.
Save shrekuu/b92b9fb4ae5341050587e52221e56095 to your computer and use it in GitHub Desktop.
给 API 请求增加出错重试, 每次出错延迟请求时间递增
// Round 1
// time: 21:26 - 21:44
// 默认最多尝试 3 次, 每次用时递减
// 缺点: 每次用时多少并不知道
// 失败: setTimeout 那里并没有 resolve, reject
function requestWithRetry(url, attempts = 3) {
  const attemptsLeft = attempts - 1;
  const maxDelayMS = 30000; // 30 seconds
  const minDelayMS = 3000; // 3 seconds
  let nextDelayMS = maxDelayMS; // 30 seconds

  if (attempts * minDelayMS < maxDelayMS) {
    nextDelayMS = maxDelayMS - attempts * minDelayMS;
  }

  console.log(new Date().toLocaleTimeString())
  return fetch(url)
    .then((res) => res.json())
    .catch((err) => {
      if (attempts === 0) {
        throw err
      }
      setTimeout(() => {
        requestWithRetry(url, attemptsLeft);
      }, nextDelayMS);
    });
}

// 写错 url, 为触发报错, 正确 url 为 https://reqbin.com/echo/get/json
requestWithRetry("https://reqbin.com/echo/get/jsons", 3).then(
  (response) => console.log(response),
  (error) => console.log('ha')
);
// ---
// Round 2
// time: 21:46 - 23:06
// 结果: 运行正常, 当前示例共发起 4 次请求, 每次在之前的延迟上加 3 秒, 最大 30 秒延迟.
function requestWithRetry(url, attempts = 3, attempted = 0) {
  const maxDelayMS = 30000; // delay 30 seconds at most
  const minDelayMS = 3000; // delay 3 seconds at least

  let nextDelayMS = minDelayMS * attempted || minDelayMS;

  if (nextDelayMS >= maxDelayMS) {
    nextDelayMS = maxDelayMS;
  }

  console.log("attempted", attempted);
  console.log('time', new Date().toLocaleTimeString());
  console.log('nextDelayMS', nextDelayMS);

  return new Promise((resolve, reject) => {
    fetch(url)
      .then((res) => res.json())
      .then((res) => resolve(res))
      .catch((err) => {
        if (attempted >= attempts) {
          reject(err);
          return;
        }

        setTimeout(() => {  
          resolve(requestWithRetry(url, attempts, attempted + 1));
        }, nextDelayMS);
      });
  });
}


// 写错 url, 为触发报错, 正确 url 为 https://reqbin.com/echo/get/json
requestWithRetry("https://reqbin.com/echo/get/jsons", 10).then(
  (response) => console.log('success', response),
  (error) => {
    console.log("error", error);
  }
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment