恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Relay 网络层错误处理实战:useMutationAction_EXPERIMENTAL 的 try/catch 捕获与降级策略

  • 首页
  • 资讯中心
  • /
  • Relay 网络层错误处理实战:useMutationAction_EXPERIMENTAL 的 try/catch 捕获与降级策略

相关资讯

Less.js混合器完全教程:Mixin参数、Guards与嵌套选择器实战 2026/9/21 2:56:47
node-redis 支持哪些 Redis 版本?官方兼容性矩阵与 CI 验证机制全解析 2026/9/21 2:56:47
AirSim安全系统详解:地理围栏与障碍物地图配置完整指南 2026/9/21 2:56:47

最新资讯

STM32程序结构全解析:从启动文件到main函数,梳理芯片上电运行流程
车载显示黑屏排查:SerDes链路DE极性配置与寄存器调试实战
BrewUI:给Homebrew穿上图形界面外套,让macOS包管理更直观
Modbus TCP轮询瘫痪的元凶:半死连接与S7-1200自愈方案
魔兽世界ID映射工具:HDF5+Streamlit实战指南
CGMA管理会计能力框架:财务人能力体检与职业发展指南

今日推荐

OneUptime 自定义探针(Custom Probe)部署实战:私网监控、代理配置与断连排障全指南
大众TL52625前端框架材料要求详解:从性能测试到落地执行
TiXL 浮点运算算子库 Lib.numbers.float 完全指南:44 个算子的参数详解、源码原理与实战串联

本周热门

BrewUI:给Homebrew套上图形界面,让macOS软件包管理更简单
BrewUI:让Homebrew包管理变得可视化与高效
公式与文本对齐全攻略:从Word到LaTeX的实用技巧

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

Relay 网络层错误处理实战:useMutationAction_EXPERIMENTAL 的 try/catch 捕获与降级策略

发布时间:2026/9/21 2:56:47
Relay 网络层错误处理实战:useMutationAction_EXPERIMENTAL 的 try/catch 捕获与降级策略 Relay 网络层错误处理实战useMutationAction_EXPERIMENTAL 的 try/catch 捕获与降级策略【免费下载链接】relayRelay is a JavaScript framework for building>项目地址: https://gitcode.com/gh_mirrors/relay29/relay导读本文以 useMutationAction-network-error-catch.md 这份端到端测试 fixture 为核心讲解 Relay 新一代 mutation HookuseMutationAction_EXPERIMENTAL在网络层失败时的错误处理模式当网络请求本身失败时commitAction返回的 Promise 会reject组件可在startTransition内用try/catch捕获异常并就地展示错误信息完全无需依赖 Error Boundary。读完本文你将掌握useMutationAction_EXPERIMENTAL的完整用法、它的 Promise 化底层实现原理以及网络错误与字段级错误catch(to: RESULT)两种失败形态的正确区分与处理策略。一、背景useMutationAction_EXPERIMENTAL 是什么useMutationAction_EXPERIMENTAL是 react-relay 提供的一个实验性 Hook它是useMutation的一个变体专门适配 React 的Action 模式React 19 的 form action /startTransitionasync 回调。它返回一个异步 action 函数commitAction调用commitAction(variables)触发一次 mutation返回PromiseTDatamutation 成功后 resolve 为响应数据网络层失败或onError触发时reject调用方可以捕获。从类型声明 useMutationAction_EXPERIMENTAL.d.ts 可以确认其签名export function useMutationAction_EXPERIMENTALTMutation extends OperationType( mutation: GraphQLTaggedNode, ): (variables: VariablesOfTMutation) PromiseTMutation[response];注意一个设计细节这里约束的是OperationTyperesponse 为unknown而非更严格的MutationParametersresponse 为Recordstring, unknown。源码注释解释了这个取舍——更严格的类型会拒绝catchmutation 的Result…联合类型响应为了兼容现代 Hook 保持一致类型上做了放宽见 d.ts 注释。二、网络层失败时发生了什么Promise reject 的底层原理理解本文主题前先看 useMutationAction_EXPERIMENTAL.js 的核心实现——它本身并不发明新的错误语义而是把传统commitMutation的两种回调包装成 Promiseconst commitAction useCallback( (variables: TVariables): PromiseTData { return new Promise((resolve, reject) { commitMutation(environment, { mutation, variables, onCompleted: (response: TData) { resolve(response); }, onError: (error: Error) { reject(error); }, }); }); }, [environment, mutation], );可以清晰看到两条错误/成功通路成功通路GraphQL 请求完成且无错误 →onCompleted被调用 →resolve(response)失败通路网络层本身失败请求没发出去、超时、HTTP 5xx、传输层异常等→commitMutation触发onError(error)→reject(error)。也就是说网络错误的暴露方式就是一个被 reject 的 Promise。本文 fixture 的核心结论由此而来组件拿到这个 Promise 后在 transition 内部用try/catch包裹await commitAction(...)即可在不引入 Error Boundary 的前提下捕获网络故障并渲染错误文案。三、完整场景拆解一个查询正常、突变失败的测试环境本 fixture 精心构造了一个不对称的网络环境用来精确隔离网络层失败这一种故障模式。3.1 配置文件relay.config.jsonfixture 中的 Relay 编译配置为标准三件套{ src: ./, schema: ./schema.graphql, language: typescript }src: ./以 fixture 目录为源码根递归收集 GraphQL 定义与组件代码schema: ./schema.graphql指向由 Grats 从服务端代码推导出的 schemalanguage: typescript生成__generated__/*.graphql.ts类型产物测试中组件直接 import 这些类型。3.2 服务端定义server.tsGrats 风格服务端用 Grats 的 JSDoc 指令声明 GraphQL 字段/** gqlQueryField */ export function greeting(): string { return Ready; } /** gqlMutationField */ export function doSomething(args: { input: string }): string { return ok; }这里greeting用于初始查询保证页面首屏渲染出 ReadydoSomething是待测试的 mutation——它本身是正常的真正故障来自客户端网络层见下文这保证了故障点被精确控制在传输层。3.3 混合网络层让 query 走真实网络、mutation 必然失败fixture 的核心技巧在App.tsx中构造了一个按操作类型分流的网络const failingMutationNetwork Network.create((operation, variables) { if (operation.operationKind mutation) { return Observable.create((sink) { sink.error(new Error(Network request failed)); }); } return gratsNetwork.execute(operation, variables, {}, null); }); const testEnvironment new Environment({ network: failingMutationNetwork });对mutation返回一个立即sink.error(new Error(Network request failed))的 Observable模拟请求发出前就失败的极端网络故障对其他操作这里是初始 query透传给 gratsNetwork一个基于graphql库execute/subscribe的内存 GraphQL 服务见 GratsNetwork.ts。这个分流网络的价值在于它把一个复杂问题mutation 网络故障在测试环境里变成了确定性的、可重复触发的事件同时让查询路径保持真实可用。四、组件实现transition 内的 try/catch 捕获完整组件代码如下与 fixture 一致import { Suspense, useState, useTransition } from react; import { RelayEnvironmentProvider, useLazyLoadQuery, useMutationAction_EXPERIMENTAL, } from react-relay; import { graphql, Environment, Network, Observable } from relay-runtime; import { gratsNetwork } from ../GratsNetwork; import { AppTestQuery } from ./__generated__/AppTestQuery.graphql; import { AppDoSomethingMutation } from ./__generated__/AppDoSomethingMutation.graphql; const failingMutationNetwork Network.create((operation, variables) { if (operation.operationKind mutation) { return Observable.create((sink) { sink.error(new Error(Network request failed)); }); } return gratsNetwork.execute(operation, variables, {}, null); }); const testEnvironment new Environment({ network: failingMutationNetwork }); function Content() { const data useLazyLoadQueryAppTestQuery( graphql query AppTestQuery { greeting } , {}, ); const commitAction useMutationAction_EXPERIMENTALAppDoSomethingMutation( graphql mutation AppDoSomethingMutation($input: String!) { doSomething(input: $input) } , ); const [errorMessage, setErrorMessage] useStatestring | null(null); const [isPending, startTransition] useTransition(); return ( div div{data.greeting}/div button disabled{isPending} onClick{() { startTransition(async () { try { await commitAction({ input: test }); } catch (err) { setErrorMessage((err as Error).message); } }); }} Submit /button {errorMessage ! null divCaught error: {errorMessage}/div} /div ); } export default function TestApp() { return ( RelayEnvironmentProvider environment{testEnvironment} Suspense fallback{divLoading.../div} Content / /Suspense /RelayEnvironmentProvider ); }逐段拆解这个模式4.1 数据声明与 mutation 注册useLazyLoadQueryAppTestQuery负责首屏查询greeting结果渲染在div{data.greeting}/divuseMutationAction_EXPERIMENTALAppDoSomethingMutation注册 mutation返回commitAction。注意泛型参数用的是编译生成的AppDoSomethingMutation类型来自__generated__/目录这样commitAction({ input: test })的参数会被静态类型检查。4.2 核心await try/catch setState点击按钮后在startTransition(async () {...})内try { await commitAction({ input: test }); } catch (err) { setErrorMessage((err as Error).message); }await commitAction(...)挂起在 mutation 的网络请求上一旦网络层失败底层onError → reject使await抛出异常进入catch分支通过setErrorMessage把错误写入本地 state组件随后渲染divCaught error: {errorMessage}/diverr as Error是因为catch到的值类型是unknown这里断言为Error以读取.message。4.3 与 Error Boundary 方案的对照值得强调的是本 fixture 与同目录下的姊妹 fixture useMutationAction-network-error-boundary.md 构成了同一故障的两种处理姿势处理方式错误去向适用场景transition 内 try/catch本文捕获后写入本地 state就地展示局部、可恢复、希望保留页面上下文Error Boundary姊妹 fixture不捕获React 将 rejection 冒泡到最近的 error boundary全局兜底、需要卸载子树并展示全屏错误页两份 fixture 的网络层构造、服务端定义完全一致差异仅在onClick中是否包裹try/catch以及根节点是否挂ErrorBoundary——这为读者提供了可对照的实验素材。4.4 isPending 的作用const [isPending, startTransition] useTransition()中的isPending用于在 transition 进行中禁用按钮disabled{isPending}避免用户重复提交。它是 React 19 async transition 的标准配套await commitAction期间isPending为truePromise 结算后自动回到false——即使请求失败isPending也会被正确复位UI 不会卡死在 pending 状态。五、运行验证markdown 驱动的端到端测试5.1 交互步骤 DSLfixture 末尾用steps代码块声明断言序列wait Ready click button Submit wait Caught error: Network request failed对应 runInteractions.js 中实现的交互 DSLwait Ready等待文本 Ready 出现对应首屏查询渲染完成click button Submit通过getByRole(button, {name: Submit})定位并user.clickwait Caught error: Network request failed等待错误文案出现验证 try/catch 分支确实把Error(Network request failed)的消息渲染了出来。这个第三行断言正是本 fixture 的验收标准如果commitAction的 rejection 没有被捕获页面将不会出现 Caught error: ... 文本测试即失败。5.2 快照验证对应的快照 useMutationAction-network-error-catch.snap.md 记录了交互后的最终 DOMdivdivReady/divbuttonSubmit/buttondivCaught error: Network request failed/div/div可以看到三个要素齐备初始数据Ready、按钮Submit、以及被捕获并展示的网络错误文案——完整印证了无 Error Boundary 也能就地展示网络错误这一结论。5.3 如何运行根据 relay-e2e-test 说明文档从仓库根目录执行yarn test:e2e单独运行本 fixtureyarn test:e2e -- --testNamePattern network-error-catch前置条件首次需在packages/relay-e2e-test下yarn install并先yarn build构建 babel-plugin-relay。编译器解析顺序为RELAY_COMPILER_BINARY环境变量 → 本地 cargo 构建的compiler/target/debug/relay→ npm 的relay-compiler兜底。测试会提取 markdown 中的代码块经 Grats relay-compiler 编译、tsc类型检查后用 React Testing Library 渲染并执行交互步骤、快照对比改动快照需yarn test:e2e -u重写。六、错误谱系try/catch 与 catch 各管一段理解本 fixture 语义的关键是不要把网络错误与字段级错误混为一谈。同目录的另一份 fixture useMutationAction-catch-field-error.md 给出了精确定义网络错误传输层失败请求未完成。commitAction的 Promisereject只能用try/catch或 Error Boundary处理。这是本文的主题。字段级错误请求成功返回但 GraphQL 响应中某个字段解析失败。默认情况下字段会静默变为null调用方无法区分null 是因为报错还是null 是因为本来就 null。字段级错误的现代解法是catch(to: RESULT)指令把字段响应包装成{ok: true, value: ...} | {ok: false, errors: [...]}联合类型调用方通过检查result.ok判断不需要 try/catch。如该 fixture 所示mutation AppFailingMutationMutation($input: String!) { failingMutation(input: $input) catch(to: RESULT) }随后代码中if (result.ok) {...} else { setMessage(Field error caught via catch); }即可分支处理而最外层catch (err)仍只负责网络错误。这也解释了为何useMutationAction_EXPERIMENTAL的 Promise 语义与catch天然互补前者承载请求层面的失败后者承载数据层面的失败两者共同覆盖了 mutation 的完整失败谱系。七、总结与最佳实践从本 fixture 及其源码实现可以提炼出useMutationAction_EXPERIMENTAL网络错误的完整处理清单理解 Promise 语义commitAction是对commitMutation的 Promise 化包装源码onError → reject、onCompleted → resolve网络失败必然表现为 rejection就地处理用 try/catch把await commitAction(...)放在startTransition(async () {...})内catch中读取(err as Error).message并setState展示无需 Error Boundary需要全局兜底时用 Error Boundary对比 useMutationAction-network-error-boundary.md 的实现不捕获的 rejection 会被 React 冒泡到最近的 error boundary区分两种错误try/catch只处理网络错误字段级错误应使用catch(to: RESULT)检查result.ok见 useMutationAction-catch-field-error.md用isPending防重复提交transition 期间禁用按钮请求失败后isPending也会自动复位可复现测试通过按operationKind分流的自定义 Networkmutation 立即sink.error、query 走真实网络即可在测试环境中确定性触发网络故障配合stepsDSL 断言错误文案的渲染形成闭环验证。这种query 正常、mutation 失败的分流网络构造是测试 Relay 应用网络错误处理最实用的基础设施之一——它不需要 mock 整个服务器只定向破坏你想验证的那条路径让错误处理的每条分支都变得可测试、可回归。【免费下载链接】relayRelay is a JavaScript framework for building>项目地址: https://gitcode.com/gh_mirrors/relay29/relay创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号