---
id: query.abort-signal
kind: contract
product: query
framework: react
locale: zh-CN
revision: 2
sourceCheckedOn: "2026-08-03"
versionRange: "^5"
verifiedAgainst: "@tanstack/react-query@5.101.4"
contentModel: 2
packages:
  - "@tanstack/react-query"
tasks:
  - "cancel-query"
  - "consume-abort-signal"
  - "stop-obsolete-fetch"
sourceRefs:
  - "https://tanstack.com/query/latest/docs/framework/react/guides/query-cancellation"
  - "https://tanstack.com/query/latest/docs/framework/react/guides/query-functions"
---

# 消费 Query 的 AbortSignal

> 将 queryFn signal 传入底层请求，使取消停止 I/O，并保留明确的缓存回滚语义。

## 执行契约

- **适用场景:** 查询可能因路由切换、参数变化或手动操作而过期，底层请求支持 AbortSignal。
- **不要使用:** 底层操作不可取消或取消会破坏必须完成的写入时，不要伪造取消语义。
- **前置检查:** 确认 queryFn 接收 signal，并把同一实例传给所有相关 I/O。
- **验证结果:** 在慢请求期间切换参数并观察旧请求中止；缓存应恢复到请求前状态且新请求完成。
- **失败模式:** 网络仍运行说明 signal 未传到底层；空数据成功说明 AbortError 被捕获并转换成普通返回值。
- **安全边界:** 取消客户端等待不会撤销服务端已经完成的副作用，因此不要把查询取消当作事务回滚。

## 默认行为

查询变为未使用时，其 Promise 默认仍可完成并把数据写入缓存。只有底层请求消费了 signal，取消才中止 Promise，并把 Query 状态恢复到发起请求前的状态。

## 请求契约

queryFn 从参数解构 signal，并传给每个相关 fetch。保持 AbortError 的原始拒绝，不要捕获后返回空数据，否则 Query 会把取消伪装成成功。

File: `src/features/issues/queries.ts`

```ts
import { queryOptions } from '@tanstack/react-query'

export const issueOptions = (issueId: string) => queryOptions({
  queryKey: ['issues', 'detail', issueId] as const,
  queryFn: async ({ signal }) => {
    const response = await fetch(`/api/issues/${issueId}`, { signal })
    if (!response.ok) throw new Error(`Issue request failed: ${response.status}`)
    return response.json()
  },
})
```

## 限制与手动取消

queryClient.cancelQueries 可以按 queryKey 手动取消；消费 signal 后也会取消底层 Promise。当前官方文档明确指出 Suspense 查询 hooks 不支持取消，因此不要把相同交互假设直接套到 useSuspenseQuery。

## Official sources

- https://tanstack.com/query/latest/docs/framework/react/guides/query-cancellation
- https://tanstack.com/query/latest/docs/framework/react/guides/query-functions
