Graffle 输出错误通道配置实战:按错误类别精确控制 return 与 throw
后端【免费下载链接】graffleSimple GraphQL Client for JavaScript. Minimal. Extensible. Type Safe. Runs everywhere.项目地址https://gitcode.com/gh_mirrors/gr/graffle点击查看免费下载本文以 Graffle 官方示例 Return Error Execution 为核心讲解如何通过output.errors配置把 GraphQL **执行错误execution与其他错误other**分别路由到返回或抛出两条通道实现同一客户端内部分错误返回、部分错误抛出的混合错误策略。读完本文你将掌握 Graffle 输出配置的完整参数语义、底层判定逻辑configuration.ts 与 handle.ts以及如何从类型层面获得与运行时完全一致的错误联合类型。场景与动机Graffle 默认采用传统 GraphQL 输出风格执行错误被包装在结果的errors字段中返回而网络错误、扩展抛出的异常等其他错误则会直接抛出。但在很多业务场景中这种一刀切的行为并不理想你想让执行错误如参数校验失败、字段解析失败以值的形式返回方便在数据流中统一处理同时又希望扩展错误、网络错误如 HTTP transport 中 fetch 抛出的异常继续以抛出异常的方式传播避免把基础设施故障和业务校验失败混为一谈。Graffle 的output.errors配置正是为此设计它把错误按类别拆分为execution与other并允许为每一类单独指定输出通道。配置总览errors 双类别与 default 解析规则在 configuration.ts 中错误类别与通道的类型定义如下export type OutputChannel throw | return export type OutputChannelConfig throw | return | default export type ErrorCategory execution | other配置键可选值含义output.errors.executionthrow/return/defaultGraphQL 执行结果中的错误传统上位于执行结果errors字段中output.errors.otherthrow/return/default其他错误HTTP transport 中 fetch 抛出的网络错误、扩展extension抛出的错误等output.defaults.errorChannelthrow/return当某个类别设为default时最终采用的通道默认值为throw两个核心语义需要明确default不是第三种通道它表示交给默认通道裁决。从 configuration.ts 的readErrorCategoryOutputChannel可以看到default会被解析为defaults.errorChannel的值export const readErrorCategoryOutputChannel ( output: Normalized, errorCategory: ErrorCategory, ): OutputChannel | false { if (output.errors[errorCategory] default) { return output.defaults.errorChannel } return output.errors[errorCategory] }execution与other的默认值都是default因此若不做任何设置二者都会落到defaults.errorChannel即throw上。默认配置的归一化结果在 configuration.tsconst default_ { defaults: { errorChannel: throw, }, envelope: { enabled: false, errors: { execution: true, other: false, }, }, errors: { execution: default, other: default, }, }完整示例execution 返回、other 抛出关联文档对应的可运行示例位于 output_return-error_return-error-execution__return-error-execution.tsimport { Graffle } from ../$/graffle/_.js const pokemon Graffle .create({ output: { envelope: false, errors: { execution: return, other: throw, }, }, }) // 1. 空 Pokemon 名称产生的 __execution__ 错误将被 ***返回***。 const result await pokemon.mutation.addPokemon({ $: { name: , hp: 1, defense: 0, attack: 0, $type: water }, // ^^ name: true, }) // 2. 内联扩展产生的 __other__ 错误将被 ***抛出***。 try { await pokemon .anyware(({ encode: _ }) { throw new Error(Something went wrong.) }) .query .pokemons({ name: true }) } catch (error) { console.log(error) }示例中的两个关键点envelope: false表示不使用信封输出即成功时直接返回data错误时按通道返回错误对象或抛出异常提交addPokemon时传入空字符串name服务端示例使用 zod 校验的 pokemon schema返回执行错误Pokemon name cannot be empty.因为execution: return这个错误不会抛出而是作为函数返回值出现。返回的执行错误长什么样示例运行后的第一个输出见 返回的执行错误输出是一个ContextualAggregateErrorContextualAggregateError errors: [ ContextualError: [ { code: too_small, minimum: 1, type: string, inclusive: true, exact: false, message: Pokemon name cannot be empty., path: [ name ] } ] context: { locations: [ { line: 2, column: 3 } ], path: [ addPokemon ] }, _tag: ContextualError ], context: {}, _tag: ContextualAggregateError,结构解读外层是ContextualAggregateError聚合了执行结果中的所有错误内层每个错误是ContextualError携带 zod 校验的原始细节code、minimum、type、path等以及 GraphQL 上下文错误所在的locations与字段路径path: [addPokemon]这两个错误类型来自wollybeard/kit的Err命名空间并在 handle.ts 中由执行结果的errors字段映射生成if (result.value.errors result.value.errors.length 0) { const error new Err.ContextualAggregateError({ message: One or more errors in the execution result., context: {}, errors: result.value.errors.map(e { if (e instanceof Error) return e const { message, ...context } e return new Err.ContextualError({ message, context }) }), }) if (isThrowExecution) throw error if (isReturnExecution) return error ... }由于本示例中execution: returnisReturnExecution为真这个聚合错误被直接返回await pokemon.mutation.addPokemon(...)得到的就是它。抛出的其他错误长什么样第二个输出是内联扩展anyware在encode钩子中抛出Error(Something went wrong.)后被包装的ContextualErrorContextualError: There was an error in the interceptor anonymous (use named functions to improve this error message) while running hook encode. context: { hookName: encode, source: extension, interceptorName: anonymous }, cause: Error: Something went wrong.解读错误消息提示在名为 anonymous 的拦截器运行encode钩子时出错并建议使用命名函数以改善错误消息context记录了出错位置的三要素hookNameencode、sourceextension、interceptorNameanonymouscause保留了你抛出的原始错误Error: Something went wrong.形成错误链便于追踪根因。因为配置为other: throw这条错误被handleOutput中的isThrowOther分支捕获并直接抛出handle.ts从而被示例中的try/catch捕获。底层判定逻辑handleOutput 的分支全景handleOutput 是理解这套配置的关键。它先读取归一化后的配置再按是否传统 GraphQL 输出 → 是否信封 → 按类别读取通道的顺序决策const isThrowOther readErrorCategoryOutputChannel(c, other) throw (!c.envelope.enabled || !c.envelope.errors.other) const isReturnOther readErrorCategoryOutputChannel(c, other) return (!c.envelope.enabled || !c.envelope.errors.other) const isThrowExecution readErrorCategoryOutputChannel(c, execution) throw (!c.envelope.enabled || !c.envelope.errors.execution) const isReturnExecution readErrorCategoryOutputChannel(c, execution) return (!c.envelope.enabled || !c.envelope.errors.execution)判定要点每个类别的throw/return判定都要求信封未启用或信封中对应错误类别未开启避免与信封内的错误字段行为冲突当result instanceof Error即其他错误如扩展异常时优先走other通道的 throw/return当执行结果带errors字段时先构建ContextualAggregateError再走execution通道的 throw/return若信封启用最终返回完整的信封data、errors、extensions否则只返回data。另外isOutputTraditionalGraphQLOutput 提供了一条快捷路径当envelope.enabled为真、envelope.errors.execution为真、envelope.errors.other为假时直接判定为传统 GraphQL 输出并原样返回执行结果——这正是Preset.traditionalGraphqlOutput的行为见 output_preset__standard-graphql.ts。类型层面返回的错误也进入返回值联合类型Graffle 的类型系统与运行时保持一致。在 handle.ts 中IfConfiguredGetOutputErrorReturns会根据配置把会返回的错误类型并入返回值type IfConfiguredGetOutputErrorReturns$OutputConfig extends Normalized | (ConfigGetOutputError$OutputConfig, execution extends return ? GraphqlKit.Request.GraphQLExecutionResultError : never) | (ConfigGetOutputError$OutputConfig, other extends return ? Ware.ResultFailure : never)也就是说当execution: return时执行错误类型GraphQLExecutionResultErrorContextualAggregateError会出现在调用返回值的联合类型中当other: return时Ware.ResultFailure如扩展错误包装也会加入。这种设计意味着你不需要try/catch就能从类型上感知这次调用可能返回错误值示例源码中的type _result typeof result正是用来在编辑器里确认这一点——result的类型是数据或执行错误的联合。更多输出错误策略同族示例对照仓库的 20_output 目录围绕同一主题提供了多个对照示例帮助你理解通道配置的全貌output_return-error.ts通过defaults: { errorChannel: return }让所有类别的错误都默认返回是全部返回的极简写法output_envelope_envelope-error__envelope-error.ts启用信封并开启envelope.errors.execution与envelope.errors.other把两类错误都嵌入信封的errors字段output_envelope_envelope_error-throw__envelope-error-throw.ts信封启用但两类错误都设为false此时即使启用信封错误仍抛出output_preset__standard-graphql.ts使用Preset.traditionalGraphqlOutput复刻传统 GraphQL 执行结果输出。对照关系可以总结为配置意图推荐写法传统输出errors 在结果里、其他错误抛出output: Preset.traditionalGraphqlOutput全部错误返回output: { defaults: { errorChannel: return } }执行错误返回、其他错误抛出output: { errors: { execution: return, other: throw } }本文主题全部错误抛入信封output: { envelope: { errors: { execution: false, other: false } } }注意事项default的解析时机errors.execution/errors.other设为default时实际通道取决于defaults.errorChannel默认throw理解这一点才能准确预测行为信封与通道的优先级信封内errors.execution/errors.other为true会接管对应类别的错误放入信封此时errors通道配置的 throw/return 判定被跳过命名拦截器从抛出的其他错误消息可见anyware内联扩展默认名为anonymous为便于排障建议在真实代码中使用命名函数作为拦截器示例运行前提示例依赖仓库中通过graffle.config.ts生成的 pokemon schema 客户端examples/$/graffle可直接在 examples 目录下运行pnpm工作区中对应的 vitest 示例任务查看输出已生成输出见outputs/20_output。赞分享后端【免费下载链接】graffleSimple GraphQL Client for JavaScript. Minimal. Extensible. Type Safe. Runs everywhere.项目地址https://gitcode.com/gh_mirrors/gr/graffle点击查看免费下载相关推荐Graffle 请求输出模式完全指南Envelope 信封与错误处理通道throw/return配置详解Graffle 请求输出模式完全指南Envelope 信封与错误处理通道throw/return配置详解 本文是 GraffleSimple Graph后端Graffle 配置指南在 Envelope 输出模式下抛出错误output.envelope.errors 详解Graffle 配置指南在 Envelope 输出模式下抛出错误output.envelope.errors 详解 本文讲解 Graffle GraphQ后端F´ Svc::StaticMemory 组件深度解析基于静态内存池的 Buffer 分配器实现与配置指南F´ Svc::StaticMemory 组件深度解析基于静态内存池的 Buffer 分配器实现与配置指南 StaticMemory 是 F´F Prime后端上一篇解放你的Steam游戏成就3步掌握成就管理神器下一篇AssetStudio终极指南5分钟掌握Unity资源提取的核心技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Spring Boot测试实战指南:单元测试、切片测试与集成测试

Spring Boot测试实战指南:单元测试、切片测试与集成测试

在Spring Boot项目里,测试的地位一直有点尴尬。老项目普遍没测试,新项目写了测试也经常停在“能跑通”的水平——启动一个SpringBootTest,调几个接口,看到绿灯就算完事。直到前阵子我在一个几乎没有测试的模块里改方法签名&#x…

2026/10/10 2:15:53 阅读更多 →
高校学科竞赛管理系统开发实战:从状态机到并发控制的JavaWeb实践

高校学科竞赛管理系统开发实战:从状态机到并发控制的JavaWeb实践

做毕业设计这几年,学科竞赛管理系统基本上每年都会出现在选题清单上。这个题目看起来很"标准"——发布竞赛、学生报名、评委打分、出成绩,听起来就是一套普通的管理系统。但真正动手做下去,你会发现这里面涉及角色权限、状态流转、…

2026/10/10 2:15:53 阅读更多 →
贴牌GTX1080专用驱动441.66:从下载安装到避坑全流程

贴牌GTX1080专用驱动441.66:从下载安装到避坑全流程

简介:针对磐镭与小影霸1080显卡用户的官方最新专用驱动441.66压缩包,集中解决系统重装后显卡无法正确识别、显示异常、游戏卡顿或分辨率不可调等常见问题。该版本来自官网渠道,相比公版驱动在硬件兼容性与默认参数上更贴合这两款非公版显卡&a…

2026/10/10 2:15:53 阅读更多 →

最新新闻

《创业之路》-1028-细读商业经典 - 主动演化基因:美国强大的底层内核与文明级别的终极优势

《创业之路》-1028-细读商业经典 - 主动演化基因:美国强大的底层内核与文明级别的终极优势

创新本质上就是人类文明的 “主动演化基因”:它让人类不再像其他生物一样,被动等待随机的变异与残酷的自然选择;而是主动地、定向地为自己引入有利的变异,用可控的试错,换取持续的成长,用持续的突破&#x…

2026/10/10 2:59:08 阅读更多 →
第 33 章 · 稀疏矩阵

第 33 章 · 稀疏矩阵

现实中的大矩阵往往大部分元素是 0(比如社交网络、物理仿真)。存一堆 0 太浪费,稀疏矩阵只存非零元素,省内存、算得快。本章讲怎么构建和使用稀疏矩阵。33.1 为什么需要稀疏矩阵 一个 10001000 的稠密矩阵要存 100 万个元素&#…

2026/10/10 2:59:08 阅读更多 →
【单片机课设毕设项目】基于单片机的物联网型厨房空气安全参数远程监控与预警系统设计 基于单片机的可燃气体泄漏远程文字告警与自动风扇控制装置设计(030119)

【单片机课设毕设项目】基于单片机的物联网型厨房空气安全参数远程监控与预警系统设计 基于单片机的可燃气体泄漏远程文字告警与自动风扇控制装置设计(030119)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/10/10 2:59:08 阅读更多 →
从1969到2026:苏净集团在100℃高温热泵赛道的技术深耕与行业实践

从1969到2026:苏净集团在100℃高温热泵赛道的技术深耕与行业实践

编者按:双碳目标背景下,工业节能需求持续增长,100℃高温热泵作为清洁高效的供热解决方案,得到了越来越多行业的关注。本文将梳理当前主流的100℃高温热泵生产厂家,重点介绍拥有半个多世纪技术沉淀的苏净集团在该领域的…

2026/10/10 2:59:08 阅读更多 →
从军工底蕴到节能先锋:苏净集团57年深耕,引领120℃高温热泵技术创新

从军工底蕴到节能先锋:苏净集团57年深耕,引领120℃高温热泵技术创新

在双碳目标推动下,工业领域对高温节能供热需求持续增长,120℃高温热泵凭借其高效节能、环保安全的特性,逐渐取代传统锅炉供热,成为工业节能改造的核心技术方向。当前国内市场中,深耕高温热泵领域的厂家众多&#xff0c…

2026/10/10 2:59:08 阅读更多 →
【BFS 解决拓扑排序】课程表

【BFS 解决拓扑排序】课程表

文章目录题目解析算法原理建图入度数组代码实现题目链接:207. 课程表 题目解析 拓扑排序(Topological sorting)要解决的问题是 如何给一个有向无环图的所有节点排序。 有向无环图 (Directed Acyclic Graph, 缩写 DAG&#xff09…

2026/10/10 2:58:07 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →