如何手动触发Apollo Client Subscription?执行时遇报错求助
解决Apollo GraphQL手动订阅触发的问题
常见报错原因及修正方案
- WebSocket链接配置缺失
确保你的Apollo Client实例已正确配置split链接,区分HTTP请求与WebSocket订阅请求,示例配置如下:
import { split, HttpLink, ApolloClient, InMemoryCache } from '@apollo/client'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { getMainDefinition } from '@apollo/client/utilities'; import { createClient } from 'graphql-ws'; // HTTP链接配置 const httpLink = new HttpLink({ uri: '你的HTTP接口地址', }); // WebSocket链接配置 const wsLink = new GraphQLWsLink(createClient({ url: '你的WebSocket服务地址', })); // 按操作类型拆分链接 const splitLink = split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, wsLink, httpLink, ); // 初始化APIClient const APIClient = new ApolloClient({ link: splitLink, cache: new InMemoryCache(), });
- 手动订阅的正确写法(含错误处理与资源清理)
直接调用APIClient.subscribe时,需处理错误逻辑,并在组件卸载或无需订阅时取消订阅,避免内存泄漏。修改你的代码如下:
// 保存订阅实例,用于后续取消操作 let subscriptionInstance; // 按钮点击触发订阅的函数 const triggerSubscription = () => { // 若已有订阅,先取消避免重复订阅 if (subscriptionInstance) { subscriptionInstance.unsubscribe(); } // 执行手动订阅 subscriptionInstance = APIClient.subscribe({ query: BULK_CREATE_PROCESS_DETAILS, variables: { id: { userId: id, }, }, }).subscribe({ next: (data) => { console.log('订阅返回数据:', data); }, error: (err) => { console.error('订阅报错:', err); }, complete: () => { console.log('订阅已完成'); }, }); }; // 组件卸载时自动取消订阅 useEffect(() => { return () => { if (subscriptionInstance) { subscriptionInstance.unsubscribe(); } }; }, []);
替代方案:通过useSubscription钩子控制订阅时机
若更倾向于使用官方钩子,可以通过skip参数控制是否自动订阅,在按钮点击时切换订阅状态:
import { useState } from 'react'; import { useSubscription } from '@apollo/client'; const [isSubscribed, setIsSubscribed] = useState(false); const { data, error, loading } = useSubscription(BULK_CREATE_PROCESS_DETAILS, { variables: { id: { userId: id }, }, skip: !isSubscribed, // skip为true时不执行订阅 onData: ({ data }) => { console.log('订阅数据:', data); }, }); // 按钮点击触发订阅 const handleSubscribe = () => { setIsSubscribed(true); }; // 停止订阅时调用 const handleUnsubscribe = () => { setIsSubscribed(false); };
内容的提问来源于stack exchange,提问作者Mirza Umair
相关产品推荐
相关产品推荐

