如何为URQL GraphQL Mutation实现全局错误处理?
全局处理Hasura Action Mutation的连接错误
问题核心
你遇到的CombinedError是urql在请求失败(如服务器宕机、网络中断)时抛出的错误,这类错误属于网络层/GraphQL服务端错误。之前mapExchange和errorExchange未触发,核心原因是你把fetchExchange放在了最前面——urql的exchange执行逻辑是请求从左到右传递,响应/错误从右到左返回,错误处理类exchange必须放在fetchExchange之前才能捕获到错误。
解决步骤
1. 调整Exchange执行顺序
将错误处理相关的errorExchange和mapExchange移到fetchExchange之前,确保错误能被正确捕获:
const createUrqlClient = (headers: StringRecord = defaultHeaders) => { return createClient({ url: GRAPHQL_ENDPOINT, fetchOptions: { headers, credentials: 'include' }, exchanges: [ // 错误处理exchange放在最前面 errorExchange({ onError: (error) => { // 处理Hasura Action连接失败的特定错误 if (error.graphQLErrors.length) { const targetError = error.graphQLErrors[0]; if (targetError.extensions?.internal?.error?.includes('http exception when calling webhook')) { // 这里添加全局通知逻辑,比如弹出错误提示 console.error('服务器连接失败,请稍后重试'); // 示例:showGlobalNotification('服务器连接异常', 'error'); } } // 处理纯网络错误(如断网、DNS解析失败) else if (error.networkError) { console.error('网络连接异常,请检查网络状态'); } }, }), mapExchange({ onResult: (result) => { // 可选:在这里补充处理结果或额外错误检查 if (result.error) { console.debug('请求结果返回错误:', result.error); } }, }), cacheExchange, fetchExchange, subscriptionExchange({ forwardSubscription(request) { const input = { ...request, query: request.query || '' }; return { subscribe(sink) { const unsubscribe = getWsClient(headers).subscribe(input, sink); return { unsubscribe }; } }; } }) ] }); };
2. 修正Mutation Hook的错误捕获逻辑
你的useAuthentication Hook未处理signOutMutation抛出的错误,需要补充try/catch确保错误能被全局exchange捕获,同时避免未捕获Promise错误:
import { useMutation } from 'urql'; export const useAuthentication = () => { const [, signOutMutation] = useMutation(SignOutAction); const signOut = async () => { try { const { data, error } = await signOutMutation({ email: appState.user.email }); if (error) return false; if (data?.signOut.isSuccess) clearAuthState(); return data?.signOut.isSuccess; } catch (err) { // 捕获极端情况下未被urql处理的错误 console.error('登出操作失败:', err); return false; } }; return { signOut }; };
3. 区分错误类型精准处理
urql的CombinedError包含两类错误,可针对性处理:
graphQLErrors: GraphQL服务端返回的错误(如Hasura Action调用webhook失败)networkError: 纯网络层错误(如断网、服务器无法访问)
关键注意事项
- Exchange顺序是核心:错误处理类exchange必须在
fetchExchange之前,否则无法捕获请求阶段的错误 - Hasura Action的错误会被包装在
graphQLErrors[0].extensions.internal.error中,可通过字段内容匹配特定错误场景 - 全局处理后,无需在每个Mutation Hook中重复编写错误处理逻辑,大幅减少代码冗余
内容的提问来源于stack exchange,提问作者Vyacheslav Fedorin
相关产品推荐
相关产品推荐

