RTK查询:maxRetries && backoff

huangapple go评论74阅读模式
英文:

RTK Query: maxRetries && backoff

问题

我正在使用RTK Query进行API调用。
我有一个要重试的变异,如果出现错误响应,我想要重新获取。
我还想要控制重试之间的延迟。

**注意:我尝试过maxRetries,但我无法控制重试之间的延迟。

**注意2:深入研究后,我发现在“extraOptions”下有一个“retryCondition”函数。我还检查了“backoff”。但我不确定如何将它们一起使用来控制延迟。
我在互联网上搜索了一下,没有找到关于backoff的内容。
此外,文档中简要提到了“retry”。

英文:

I am using RTK Query to perform my API calls.
I have a mutation which I want to retry fetching if got the an error response.
I also want to control the delay between the retries.

** Note: I tried maxRetries, but I have no control over the delay between retries

** Note 2: after digging deep, I found the "retryCondition" fn under "extraOptions". Also, I checked the "backoff". but I am not sure how to use these together to control the delay.
I searched over the internet && found nothing about backoff
Also the documentation mentions the "retry" briefly.

答案1

得分: 1

你说得对,文档没有很好地展示这个功能,我不得不在代码库中寻找信息。retry 函数接受两个参数,第一个是基本查询函数,第二个是默认选项(RetryOptions)配置对象。

查看RetryOptions类型声明

export type RetryOptions = {
  /**
   * 用于确定重试之间延迟的函数
   */
  backoff?: (attempt: number, maxRetries: number) => Promise<void>
} & (
  | {
      /**
       * 查询将被重试的次数(默认值:5)
       */
      maxRetries?: number
      retryCondition?: undefined
    }
  | {
      /**
       * 用于确定是否应尝试重试的回调函数。
       * 返回 `true` 表示进行另一次重试,`false` 表示提前停止尝试。
       */
      retryCondition?: RetryConditionFunction
      maxRetries?: undefined
    }
)

backoff 属性是你感兴趣的部分

(attempt: number, maxRetries: number) => Promise<void>

它是一个接受尝试次数和最大重试次数参数并返回 Promise 的函数。幸运的是,已经有一个默认的回退函数可供参考:

/**
 * 基于尝试次数的指数回退。
 *
 * @remarks
 * 1. 600ms * random(0.4, 1.4)
 * 2. 1200ms * random(0.4, 1.4)
 * 3. 2400ms * random(0.4, 1.4)
 * 4. 4800ms * random(0.4, 1.4)
 * 5. 9600ms * random(0.4, 1.4)
 *
 * @param attempt - 当前尝试次数
 * @param maxRetries - 最大重试次数
 */
async function defaultBackoff(attempt: number = 0, maxRetries: number = 5) {
  const attempts = Math.min(attempt, maxRetries)

  const timeout = ~~((Math.random() + 0.4) * (300 << attempts)) // 强制转换为正整数,以防将其变为选项
  await new Promise((resolve) =>
    setTimeout((res: any) => resolve(res), timeout)
  )
}

在我看来,这是一个相当不错的默认函数,但如果需要的话,你可以构建自己的回退函数。

示例:

1 秒,2 秒,3 秒,... 最大重试秒数

const customBackOff = async (attempt = 0, maxRetries = 5) => {
  const attempts = Math.min(attempt, maxRetries);

  await new Promise(resolve => {
    setTimeout(resolve, attempts * 1000);
  });
};

每次重试 1 秒

const customBackOff = async (attempt = 0, maxRetries = 5) => {
  await new Promise(resolve => {
    setTimeout(resolve, 1000);
  });
};

查找数组中的值。

const backoffDelays = [500, 2000, 5000];

const customBackOff = async (attempt = 0, maxRetries = 5) => {
  const attempts = Math.min(backoffDelays.length - 1, maxRetries);

  await new Promise(resolve => {
    setTimeout(resolve, backoffDelays[attempts]);
  });
};

按照文档中的示例来装饰你的基本查询函数。

const customBaseQuery = retry(
  fetchBaseQuery({ baseUrl: '/' }),
  { backoff: customBackOff, maxRetries: 5 }
);

export const api = createApi({
  baseQuery: customBaseQuery,
  endpoints: (build) => ({
    ....
  }),
});
英文:

You're right, the docs don't surface this feature well enough and I had to go spelunking in the repo to find the information. The retry function takes 2 arguments, first is the base query function and second is a default options (RetryOptions) configuration object.

See RetryOptions type declaration:

> export type RetryOptions = {
> /**
> * Function used to determine delay between retries
> /
> backoff?: (attempt: number, maxRetries: number) => Promise<void>
> } & (
> | {
> /
*
> * How many times the query will be retried (default: 5)
> /
> maxRetries?: number
> retryCondition?: undefined
> }
> | {
> /
*
> * Callback to determine if a retry should be attempted.
> * Return true for another retry and false to quit trying prematurely.
> */
> retryCondition?: RetryConditionFunction
> maxRetries?: undefined
> }
> )

The backoff property is what you're interested in

(attempt: number, maxRetries: number) =&gt; Promise&lt;void&gt;

It's a function that takes attempt and max retries arguments and returns a Promise. Fortunately there's already a default backoff function you can reference:

> /**
> * Exponential backoff based on the attempt number.
> *
> * @remarks
> * 1. 600ms * random(0.4, 1.4)
> * 2. 1200ms * random(0.4, 1.4)
> * 3. 2400ms * random(0.4, 1.4)
> * 4. 4800ms * random(0.4, 1.4)
> * 5. 9600ms * random(0.4, 1.4)
> *
> * @param attempt - Current attempt
> * @param maxRetries - Maximum number of retries
> */
> async function defaultBackoff(attempt: number = 0, maxRetries: number = 5) {
> const attempts = Math.min(attempt, maxRetries)
>
> const timeout = ~~((Math.random() + 0.4) * (300 << attempts)) // Force a positive int in the case we make this an option
> await new Promise((resolve) =>
> setTimeout((res: any) => resolve(res), timeout)
> )
> }

IMO this is a pretty good default function, but you could construct your own if necessary.

Examples:

1 second, 2 seconds, 3 seconds, ...maxRetries seconds

const customBackOff = async (attempt = 0, maxRetries = 5) =&gt; {
  const attempts = Math.min(attempt, maxRetries);

  await new Promise(resolve =&gt; {
    setTimeout(resolve, attempts * 1000);
  });
};

1 second each retry

const customBackOff = async (attempt = 0, maxRetries = 5) =&gt; {
  await new Promise(resolve =&gt; {
    setTimeout(resolve, 1000);
  });
};

Lookup in array.

const backoffDelays = [500, 2000, 5000];

const customBackOff = async (attempt = 0, maxRetries = 5) =&gt; {
  const attempts = Math.min(backoffDelays.length - 1, maxRetries);

  await new Promise(resolve =&gt; {
    setTimeout(resolve, backoffDelays[attempts]);
  });
};

Follow the example from the documentation to decorate your base query function.

const customBaseQuery = retry(
  fetchBaseQuery({ baseUrl: &#39;/&#39; }),
  { backoff: customBackOff, maxRetries: 5 }
);

export const api = createApi({
  baseQuery: customBaseQuery,
  endpoints: (build) =&gt; ({
    ....
  }),
});

huangapple
  • 本文由 发表于 2023年8月4日 05:18:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831664.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定