React中如何终止Apollo Client未完成的长时查询?
解决Apollo Client 3.x中止长时查询的问题
在Apollo Client 3.7.17中,useLazyQuery并没有直接暴露abort方法,但可以通过以下两种方式实现查询中止:
方式一:手动保存查询引用,实现手动中止或组件卸载时自动中止
当调用useLazyQuery返回的触发函数(比如getData)时,它会返回一个包含cancel()方法的查询对象。我们可以用useRef保存这个对象,在需要时调用cancel()来中止请求,同时在组件卸载时自动清理未完成的查询。
示例代码:
import { useGetDataLazyQuery } from './generated/graphql'; import { useEffect, useRef } from 'react'; const MyComponent = () => { const [getData, { loading }] = useGetDataLazyQuery({ fetchPolicy: "no-cache" }); // 保存当前正在运行的查询引用 const activeQueryRef = useRef(null); const fetchData = async () => { // 触发查询并保存引用 const query = getData(); activeQueryRef.current = query; try { // 等待查询完成 const result = await query; // 处理查询结果 console.log('查询结果:', result); } catch (error) { // 捕获中止错误,避免控制台报错 if (error.name !== 'AbortError') { console.error('查询失败:', error); } } finally { // 清除引用 activeQueryRef.current = null; } }; // 组件卸载时自动中止未完成的查询 useEffect(() => { return () => { if (activeQueryRef.current) { activeQueryRef.current.cancel(); } }; }, []); // 手动中止查询的方法 const abortQuery = () => { if (activeQueryRef.current) { activeQueryRef.current.cancel(); activeQueryRef.current = null; } }; return ( <div> <button onClick={fetchData}>触发查询</button> {loading && <p>加载中...</p>} <button onClick={abortQuery} disabled={!loading}>中止查询</button> </div> ); };
方式二:依赖Apollo Client的自动取消机制
Apollo Client默认会在组件卸载时自动取消未完成的查询请求。如果你的场景是用户跳转页面导致组件卸载,那么无需额外代码,Apollo会自动终止对应的请求,避免资源浪费。但如果需要在组件未卸载时手动中止查询,还是需要使用方式一。
关键说明
- 调用
cancel()方法会抛出AbortError,需要在try/catch中捕获并处理,避免控制台出现未捕获错误。 - 确保在查询完成或中止后清除
useRef中的引用,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Ar26
相关产品推荐
相关产品推荐

