文档
错误处理

错误处理

如果在 fetcher 中抛出错误,hook 会将其作为 error 返回。

const anQuery = query({
  fether: () => axios.get(url),
});
 
// ...
const { data, error } = useQuery({ query: anQuery });

如果 fetch promise 被 reject,将定义 error 对象。

状态码和错误对象

有时我们希望 API 在返回状态码的同时返回一个错误对象。它们对客户端都是有用的。

我们可以自定义 fetcher 以返回更多信息。如果状态码不是 2xx,我们则认为它是一个错误,即使它可以被解析为 JSON:

const anQuery = query({
  fether: async (url) => {
    const res = await fetch(url);
 
    // 如果状态码不在 200-299 的范围内,
    // 我们仍然尝试解析并抛出它。
    if (!res.ok) {
      const error = new Error("An error occurred while fetching the data.");
      // 将额外的信息附加到错误对象上。
      error.info = await res.json();
      error.status = res.status;
      throw error;
    }
 
    return res.json();
  },
});
 
// ...
const { data, error } = useQuery({ query: anQuery });
// error.info === {
//   message: "You are not authorized to access this resource.",
//   documentation_url: "..."
// }
// error.status === 403
💡

注意:dataerror 可以同时存在。所以 UI 可以在知道即将到来的请求失败时显示现有数据。

这里有一个示例。

错误重试

在出现错误时 Quaere 使用指数退避算法 (opens in a new tab)重发请求。该算法允许应用从错误中快速恢复,而不会浪费资源频繁地重试。

你还可以通过 retryretryDelay 选项覆盖该行为:

useQuery({
  query: anQuery,
  retry: 3,
  retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
});

这个回调让你可以灵活的根据各种条件重试。你也可以通过设置 retry: false 来禁用它。

也可以通过全局配置 context 来提供它。

全局错误报告

你总是可以响应性的在组件内部得到 error 对象。但如果你想要全局处理错误,可以创建自定义的 QueryCacheMutationCache 监听错误事件:

import { createQueryCache, createMutationCache } from "quaere"
 
const queryCache = createQueryCache({
  onError: (error) => {
    console.log(error);
  },
});
 
const mutationCache = createMutationCache({
  onError: (error) => {
    console.log(error);
  },
});
 
const queryClient = createQueryClient({
    queryCache,
    mutationCache
})
 
<QueryClientProvider client={queryClient}>
  <App />
</QueryClientProvider>

某个错误报告

const unsubscribe = queryCache.subscribe(
  { query, variables },
  ({ action, queryInfo }) => {
    if (action.type === "error") {
      console.log(queryInfo.error);
    }
  }
);
 
const unsubscribe = mutationCache.subscribe(
  { mutation, variables },
  ({ action, mutationInfo }) => {
    if (action.type === "error") {
      console.log(mutationInfo.error);
    }
  }
);