译零 TransZero · TanStack Query 中文文档
主站

查询取消

更新于 2026-11-02 React 查看英文原文 ↗

TanStack Query 会为每个查询函数提供一个 AbortSignal 实例。当查询变为过期或非活跃状态时,该 signal 将被中止。这意味着所有查询均可取消;你也可以在查询函数内响应取消操作(如需)。最棒之处在于,你仍可继续使用常规的 async/await 语法,同时获得自动取消的所有优势。

AbortController API 在 大多数运行时环境 中可用;但若你的运行时环境不支持它,则需提供 polyfill。目前有 多个可用选项。

默认行为

默认情况下,在 Promise 解析完成前已卸载或不再使用的查询 不会 被取消。这意味着 Promise 解析后,所得数据将保留在缓存中。这在你已发起查询、但组件在查询完成前即被卸载时非常有用。若之后再次挂载该组件,且该查询尚未被垃圾回收,则数据依然可用。

然而,若你消费了 AbortSignal,Promise 将被取消(例如中止 fetch 请求),因此该查询也必须被取消。取消查询将使其状态 回退 至先前状态。

使用 fetch

TypeScript
1const query = useQuery({2  queryKey: ['todos'],3  queryFn: async ({ signal }) => {4    const todosResponse = await fetch('/todos', {5      // Pass the signal to one fetch6      signal,7    })8    const todos = await todosResponse.json()9 10    const todoDetails = todos.map(async ({ details }) => {11      const response = await fetch(details, {12        // Or pass it to several13        signal,14      })15      return response.json()16    })17 18    return Promise.all(todoDetails)19  },20})

使用 axios v0.22.0+

TypeScript
1import axios from 'axios'2 3const query = useQuery({4  queryKey: ['todos'],5  queryFn: ({ signal }) =>6    axios.get('/todos', {7      // Pass the signal to `axios`8      signal,9    }),10})

使用低于 v0.22.0 版本的 axios

TypeScript
1import axios from 'axios'2 3const query = useQuery({4  queryKey: ['todos'],5  queryFn: ({ signal }) => {6    // Create a new CancelToken source for this request7    const CancelToken = axios.CancelToken8    const source = CancelToken.source()9 10    const promise = axios.get('/todos', {11      // Pass the source token to your request12      cancelToken: source.token,13    })14 15    // Cancel the request if TanStack Query signals to abort16    signal?.addEventListener('abort', () => {17      source.cancel('Query was cancelled by TanStack Query')18    })19 20    return promise21  },22})

使用 XMLHttpRequest

TypeScript
1const query = useQuery({2  queryKey: ['todos'],3  queryFn: ({ signal }) => {4    return new Promise((resolve, reject) => {5      var oReq = new XMLHttpRequest()6      oReq.addEventListener('load', () => {7        resolve(JSON.parse(oReq.responseText))8      })9      signal?.addEventListener('abort', () => {10        oReq.abort()11        reject()12      })13      oReq.open('GET', '/todos')14      oReq.send()15    })16  },17})

使用 graphql-request

可在客户端 request 方法中设置 AbortSignal。

TypeScript
1const client = new GraphQLClient(endpoint)2 3const query = useQuery({4  queryKey: ['todos'],5  queryFn: ({ signal }) => {6    client.request({ document: query, signal })7  },8})

使用低于 v4.0.0 版本的 graphql-request

可在 GraphQLClient 构造函数中设置 AbortSignal。

TypeScript
1const query = useQuery({2  queryKey: ['todos'],3  queryFn: ({ signal }) => {4    const client = new GraphQLClient(endpoint, {5      signal,6    })7    return client.request(query, variables)8  },9})

手动取消

你可能需要手动取消某个查询。例如,若请求耗时较长,你可以允许用户点击取消按钮来中止请求。为此,只需调用 queryClient.cancelQueries({ queryKey }),它将取消查询并将其状态回退至先前状态。若你已在查询函数中消费了传入的 signal,TanStack Query 还将额外取消该 Promise。

TypeScript
1const query = useQuery({2  queryKey: ['todos'],3  queryFn: async ({ signal }) => {4    const resp = await fetch('/todos', { signal })5    return resp.json()6  },7})8 9const queryClient = useQueryClient()10 11return (12  <button13    onClick={(e) => {14      e.preventDefault()15      queryClient.cancelQueries({ queryKey: ['todos'] })16    }}17  >18    Cancel19  </button>20)

Cancel Options

取消选项用于控制查询取消操作的行为。

TypeScript
1// Cancel specific queries silently2await queryClient.cancelQueries({ queryKey: ['posts'] }, { silent: true })

取消选项对象支持以下属性:

  • silent?: boolean
    • 设为 true 时,将抑制 CancelledError 向观察者(例如 onError 回调)及相关通知的传播,并返回重试 Promise 而非拒绝该 Promise。
    • 默认值为 false
  • revert?: boolean
    • 设为 true 时,将从进行中的拉取操作前一刻恢复查询状态(数据和状态),并将 fetchStatus 重置为 idle;仅当此前无数据时才抛出错误。
    • 默认值为 true

局限性

在使用 Suspense Hook(即 useSuspenseQuery、useSuspenseQueries 和 useSuspenseInfiniteQuery)时,取消功能不可用。

本页为 TanStack Query 文档(React 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

译自上游 59d11de