前端
PythonJava运维数据库
TanStack Query
TanStack Query
  • getting started
    • 快速开始
    • 开发工具
    • Typescript
    • 默认配置
    • 网络模式
  • Query
    • 查询
    • 查询键
    • 查询函数
    • 查询选项
    • 并行查询
    • 有依赖的查询
    • 查询状态指示器
    • 窗口聚焦重新获取数据
    • 禁用/暂停查询
    • 查询重试
    • 分页查询
    • 无限查询
    • 初始化查询数据
  • 占位符
  • Mutation
    • 修改 Mutations
    • 主动查询失效 Query Invalidation
    • 修改导致的失效 Invalidation From Mutations
    • 通过修改的数据更新查询内容
    • 乐观更新
  • 取消查询
  • 默认查询函数
  • 过滤器
  • Suspense
  • 缓存数据
  • Api Reference
    • QueryClient
    • QueryCache
    • MutationCache
    • QueryObserver QueriesObserver
    • InfiniteQueryObserver
    • FocusManager
    • NotifyManager
    • useQuery
    • useQueries useInfiniteQuery
    • useMutation
    • useIsFetching
    • useIsMutating
    • useMutationState
    • useSuspenseQuery
    • useSuspenseInfiniteQuery
    • useSuspenseQueries
    • QueryClientProvider
    • useQueryClient
    • queryOptions
    • infiniteQueryOptions
    • QueryErrorResetBoundary
    • useQueryErrorResetBoundary
    • hydration
由 GitBook 提供支持
在本页

这有帮助吗?

取消查询

Query Cancellation(查询取消)

TanStack Query 为每个查询函数提供了一个 AbortSignal 实例。当查询变得过时或不再活跃时,该信号将被触发中止。这意味着所有查询都是可取消的,并且如果需要,你可以在查询函数内部对取消作出响应。最棒的地方在于,这让你能够继续使用普通的 async/await 语法,同时享受自动取消的所有好处。

AbortController API 在大多数运行时环境中可用,但如果你的运行时环境不支持它,则需要提供一个 polyfill(兼容补丁)。市面上有多个可用的 polyfill。

默认行为

默认情况下,在 Promise 解析完成之前,卸载(unmount)或未使用的查询不会被取消。这意味着在 Promise 解析后,结果数据仍然会保留在缓存中。如果你已经发起了一个查询,但在其完成之前卸载了组件,那么如果再次挂载组件,并且查询尚未被垃圾回收,数据仍然可用。

然而,如果你使用了 AbortSignal,则 Promise 将被取消(例如,中止 fetch 请求),因此,查询也必须被取消。取消查询后,其状态将恢复到之前的状态。

使用 fetch

const query = useQuery({
  queryKey: ["todos"],
  queryFn: async ({ signal }) => {
    const todosResponse = await fetch("/todos", {
      // 传递 signal 以支持取消
      signal,
    });
    const todos = await todosResponse.json();

    const todoDetails = todos.map(async ({ details }) => {
      const response = await fetch(details, {
        // 也可以传递到多个 fetch 请求中
        signal,
      });
      return response.json();
    });

    return Promise.all(todoDetails);
  },
});

使用 axios(v0.22.0 及以上版本)

import axios from "axios";

const query = useQuery({
  queryKey: ["todos"],
  queryFn: ({ signal }) =>
    axios.get("/todos", {
      // 传递 signal 给 `axios`
      signal,
    }),
});

使用 axios(v0.22.0 以下版本)

import axios from "axios";

const query = useQuery({
  queryKey: ["todos"],
  queryFn: ({ signal }) => {
    // 为请求创建一个新的 CancelToken
    const CancelToken = axios.CancelToken;
    const source = CancelToken.source();

    const promise = axios.get("/todos", {
      // 传递 cancelToken
      cancelToken: source.token,
    });

    // 如果 TanStack Query 触发中止,则取消请求
    signal?.addEventListener("abort", () => {
      source.cancel("Query was cancelled by TanStack Query");
    });

    return promise;
  },
});

使用 XMLHttpRequest

const query = useQuery({
  queryKey: ["todos"],
  queryFn: ({ signal }) => {
    return new Promise((resolve, reject) => {
      var oReq = new XMLHttpRequest();
      oReq.addEventListener("load", () => {
        resolve(JSON.parse(oReq.responseText));
      });
      signal?.addEventListener("abort", () => {
        oReq.abort();
        reject();
      });
      oReq.open("GET", "/todos");
      oReq.send();
    });
  },
});

使用 graphql-request

AbortSignal 可以在 client.request 方法中设置:

const client = new GraphQLClient(endpoint);

const query = useQuery({
  queryKey: ["todos"],
  queryFn: ({ signal }) => {
    client.request({ document: query, signal });
  },
});

使用 graphql-request(v4.0.0 以下版本)

AbortSignal 可以在 GraphQLClient 构造函数中设置:

const query = useQuery({
  queryKey: ["todos"],
  queryFn: ({ signal }) => {
    const client = new GraphQLClient(endpoint, { signal });
    return client.request(query, variables);
  },
});

手动取消

在某些情况下,你可能希望手动取消查询。例如,如果请求耗时过长,你可以让用户点击“取消”按钮来终止请求。要实现此功能,只需调用 queryClient.cancelQueries({ queryKey }),这将取消查询并将其状态恢复到之前的状态。如果你的查询函数使用了 signal,TanStack Query 还会额外取消 Promise。

const query = useQuery({
  queryKey: ["todos"],
  queryFn: async ({ signal }) => {
    const resp = await fetch("/todos", { signal });
    return resp.json();
  },
});

const queryClient = useQueryClient();

return (
  <button
    onClick={(e) => {
      e.preventDefault();
      queryClient.cancelQueries({ queryKey: ["todos"] });
    }}
  >
    Cancel
  </button>
);

限制

取消功能在使用以下 Suspense hooks 时无效:

  • useSuspenseQuery

  • useSuspenseQueries

  • useSuspenseInfiniteQuery

上一页乐观更新下一页默认查询函数

最后更新于2个月前

这有帮助吗?