英文:
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
)配置对象。
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) => Promise<void>
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) => {
const attempts = Math.min(attempt, maxRetries);
await new Promise(resolve => {
setTimeout(resolve, attempts * 1000);
});
};
1 second each retry
const customBackOff = async (attempt = 0, maxRetries = 5) => {
await new Promise(resolve => {
setTimeout(resolve, 1000);
});
};
Lookup in array.
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]);
});
};
Follow the example from the documentation to decorate your base query function.
const customBaseQuery = retry(
fetchBaseQuery({ baseUrl: '/' }),
{ backoff: customBackOff, maxRetries: 5 }
);
export const api = createApi({
baseQuery: customBaseQuery,
endpoints: (build) => ({
....
}),
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论