这是使用React Query与TypeScript的系列文章中的另一篇文章。
在这篇文章中,我们将探讨React Query中的重试功能,这在通过脆弱的连接获取数据时非常有用。在实现我们自己的自定义重试逻辑之前,我们首先探索默认的重试行为。

我们的起点
我们将从我们在入门文章中完成的代码开始。
这就是获取函数的样子:
type Character = {
name: string;
};
type Params = {
queryKey: [string, { id: number }];
};
async function getCharacter(params: Params) {
const [, { id }] = params.queryKey;
const response = await fetch(`https://swapi.dev/api/people/${id}/`);
if (!response.ok) {
throw new Error("Problem fetching data");
}
const character = await response.json();
assertIsCharacter(character);
return character;
}
function assertIsCharacter(character: any): asserts character is Character {
if (!("name" in character)) {
throw new Error("Not character");
}
}
这是包含查询的组件:
export function App() {
const { status, error, data } = useQuery<Character, Error>(
["character", { id: 1 }],
getCharacter
);
if (status === "loading") {
return <div>...</div>;
}
if (status === "error") {
return <div>{error!.message}</div>;
}
return data ? <h3>{data.name}</h3> : null;
}
默认的重试行为
让我们改变fetch 的调用,使资源没有被找到:
const response = await fetch(`https://swapi.dev/api/unknown/${id}/`);
读取函数现在会引发一个错误,让我们看看会发生什么:

在放弃之前,获取函数最多重试三次。每次重试的延迟都会变长--1秒、2秒和4秒。
防止重试
重试行为可以用retry 选项来覆盖。要完全关闭重试,我们将retry 设置为false :
const { status, error, data } = useQuery<Character, Error>(
["character", { id: 1 }],
getCharacter,
{ retry: false });
改变重试的次数
要改变重试的次数,我们可以将retry 设置为我们需要的次数:
const { status, error, data } = useQuery<Character, Error>(
["character", { id: 1 }],
getCharacter,
{
retry: 5 }
);
上述查询最多重试5次。
基于获取错误的重试
retry 也可以被设置为一个函数。当重试逻辑依赖于获取错误时,这很有用。
在我们尝试这个方法之前,让我们创建一个扩展了标准Error 类的类,在错误中存储HTTP状态代码:
class FetchError extends Error {
constructor(public message: string, public statusCode: number) {
super(message);
}
}
我们现在可以改变获取函数来引发这种类型的错误:
async function getCharacter({
queryKey,
}: {
queryKey: [string, { id: number }];
}) {
...
if (!response.ok) {
throw new FetchError("Problem fetching character", response.status); }
...
}
我们现在可以实现一个重试函数,如下所示:
const { status, error, data } = useQuery<Character, FetchError>(
["character", { id: 1 }],
getCharacter,
{
retry: (failureCount, error) => error.statusCode === 404 && failureCount <= 3 ? true : false, }
);
重试函数接收失败的次数和从获取函数抛出的错误对象。
重试函数预计将返回一个布尔值,表示是否应该重试。
在这个例子中,如果没有找到资源,查询最多重试3次。
改变重试延迟
重试延迟可以通过retryDelay 选项来改变:
const { status, error, data } = useQuery<Character, FetchError>(
["character", { id: 1 }],
getCharacter,
{
retry: (failureCount, error) =>
error.statusCode === 404 && failureCount <= 3 ? true : false,
retryDelay: retryCount => retryCount === 0 ? 1000 : 5000 }
);
retryDelay 被设置为一个函数,它接收重试次数并返回等待下一次重试的毫秒数。
在上面的例子中,第一次重试延迟为1秒,随后的重试为5秒。
不错😊