如何在Apollo Client中正确识别受控取消的请求
问题描述
我在React应用中实现了“取消查询”功能:当已有GraphQL请求运行时,提交新请求会取消旧请求。具体实现代码如下:
const [searchQuery] = useLazyQuery<QueryResponse>(GET_QUERY_WITH_FACETS, { notifyOnNetworkStatusChange: true, onError: (err) => { if (err.message !== ABORTED_ERROR) { messageStore.addMessage('Error', err.message, 'error'); setLoading(false); } }, context: { fetchOptions: { signal: aborterRef.signal, }, }, }); // ... const fetchResults = async () => { aborterRef.abort(); setAbortRef(new AbortController()); searchQuery(); }
其中ABORTED_ERROR = 'The operation was aborted.'。我在onError中做判断是因为主动取消的请求不算真正的错误,不想展示给用户或影响页面。但不同浏览器的错误消息不一致:
- Firefox:
The operation was aborted. - Chrome:
The user aborted a request
这种通过错误消息判断的方式不够可靠,请问有没有方法识别这是受控取消的请求?或者有没有其他方法避免第一个查询在用户提交第二个请求时继续执行?
解决方案
1. 利用Apollo Client的AbortError类型判断
你用的是Apollo Client的useLazyQuery,可以直接通过错误类型判断是否为主动取消的请求,完全不需要依赖浏览器返回的错误文本。
先引入AbortError:
import { AbortError } from '@apollo/client/errors';
然后修改onError回调:
onError: (err) => { // 仅当错误不是主动触发的AbortError时,才处理错误提示 if (!(err instanceof AbortError)) { messageStore.addMessage('Error', err.message, 'error'); setLoading(false); } }
这种方式不受浏览器差异影响,是最可靠的判断方案。
2. 自定义请求标记(备选方案)
如果因版本限制无法使用AbortError类型,可以给主动取消的请求添加自定义标识:比如给每个请求绑定唯一ID,或者在AbortController上附加标记,然后在onError中通过上下文或错误的额外属性判断。不过这种方式需要额外的状态管理,不如第一种简洁。
3. 优化请求取消逻辑
你当前的取消逻辑是先终止旧控制器,再创建新控制器,这个流程没问题。另外也可以结合Apollo Client的skip选项控制请求触发,但skip更多用于条件性发起请求,不如AbortController直接终止请求高效。
内容的提问来源于stack exchange,提问作者L_Cleo
相关产品推荐
相关产品推荐

