在Vue3 Composition API中终止Apollo待处理查询求助
取消Apollo Query结果返回的可行方案
以下是几种经过验证的取消Apollo Query的有效方法,针对不同场景选择合适的方案:
1. 通过skip变量直接中止查询
这是最常用的控制方式,当skip设为true时,不仅不会发起新查询,正在进行中的请求也会被中止,且不会返回结果。
import { useQuery } from '@apollo/client'; import GET_DATA_QUERY from './queries/GetData'; function DataComponent({ shouldCancel }) { const { data, loading } = useQuery(GET_DATA_QUERY, { skip: shouldCancel, // 布尔值控制是否取消查询 variables: { id: 'target-id' } }); // 当shouldCancel为true时,data会保持之前的值或undefined,不会更新为新查询结果 return ( <div> {loading && <p>加载中...</p>} {data && !shouldCancel && <p>{data.content}</p>} </div> ); }
2. 手动调用查询的cancel方法
如果使用useLazyQuery或手动发起查询,可以获取到查询的cancel函数,主动调用即可中止请求。
针对useLazyQuery的场景:
import { useLazyQuery } from '@apollo/client'; import GET_DATA_QUERY from './queries/GetData'; function LazyDataComponent() { const [fetchData, { data, loading }] = useLazyQuery(GET_DATA_QUERY); let cancelQuery; const handleFetch = async () => { // 发起查询时获取cancel函数 const queryResult = await fetchData({ variables: { id: 'target-id' } }); cancelQuery = queryResult.cancel; }; const handleCancel = () => { if (cancelQuery) { cancelQuery(); // 主动取消查询 } }; return ( <div> <button onClick={handleFetch}>获取数据</button> <button onClick={handleCancel} disabled={!loading}>取消请求</button> {loading && <p>加载中...</p>} {data && <p>{data.content}</p>} </div> ); }
手动通过Apollo Client发起查询的场景:
import { ApolloClient, InMemoryCache } from '@apollo/client'; const client = new ApolloClient({ uri: '/graphql', cache: new InMemoryCache(), }); // 发起查询并保存引用 const queryRef = client.query({ query: GET_DATA_QUERY, variables: { id: 'target-id' } }); // 需要取消时调用 queryRef.cancel();
3. 使用AbortController控制请求
通过Apollo Client的context配置传入AbortController的signal,利用浏览器原生的中断机制取消请求。
import { useQuery } from '@apollo/client'; import GET_DATA_QUERY from './queries/GetData'; function AbortableComponent() { const abortController = new AbortController(); const { data, loading } = useQuery(GET_DATA_QUERY, { variables: { id: 'target-id' }, context: { fetchOptions: { signal: abortController.signal, // 绑定中断信号 }, }, }); const handleCancel = () => { abortController.abort(); // 触发中断 }; return ( <div> <button onClick={handleCancel} disabled={!loading}>取消请求</button> {loading && <p>加载中...</p>} {data && <p>{data.content}</p>} </div> ); }
4. 组件卸载时自动取消查询
在组件卸载前取消订阅或中止查询,避免组件卸载后仍收到结果导致错误。
import { useApolloClient } from '@apollo/client'; import { useEffect } from 'react'; import GET_DATA_QUERY from './queries/GetData'; function AutoCancelComponent({ itemId }) { const client = useApolloClient(); useEffect(() => { const querySubscription = client.watchQuery({ query: GET_DATA_QUERY, variables: { id: itemId }, }).subscribe({ next: (result) => console.log('数据更新:', result.data), error: (err) => console.error('查询错误:', err), }); // 组件卸载时取消订阅,同时中止查询 return () => { querySubscription.unsubscribe(); }; }, [client, itemId]); return <div>组件内容</div>; }
注意事项
- 确保你的Apollo Client版本在
3.0+,旧版本部分方法可能不兼容 - 如果缓存中已有查询数据,
skip设为true不会清除缓存,若需清除可调用client.cache.evict({ query: GET_DATA_QUERY, variables: { id: 'target-id' } }) - 主动取消查询后,错误对象会包含
canceled: true属性,可通过error.graphQLErrors.some(e => e.extensions?.canceled)判断是否为主动取消
内容的提问来源于stack exchange,提问作者xXSteroidsXx
相关产品推荐
相关产品推荐

