首页/新闻资讯/正文详情

TypeGraphQL 订阅(Subscriptions)完整实战指南:@Subscription 装饰器、PubSub 主题与分布式部署

发布时间:2026/9/27 7:00:21 来源:云帆数科 栏目:资讯中心
TypeGraphQL 订阅(Subscriptions)完整实战指南:@Subscription 装饰器、PubSub 主题与分布式部署
后端GraphQLAPI设计【免费下载链接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!项目地址https://gitcode.com/gh_mirrors/ty/type-graphql点击查看免费下载GraphQL 提供 Query 与 Mutation 分别满足读取和写入场景但客户端往往还希望在关注的数据发生变化时被服务器主动推送更新。为此 GraphQL 定义了第三种操作——Subscription订阅。本指南以 TypeGraphQL 的官方订阅文档为主体结合仓库源码与 simple-subscriptions 示例系统讲解如何使用Subscription()装饰器声明订阅解析器、通过pubsub系统发布主题事件、按需过滤与动态主题、接入 Redis 等分布式 PubSub 以及搭建支持 WebSocket 的订阅服务端。读完本文你将能独立实现一个可扩展、可测试的 GraphQL 实时推送 API。一、订阅在 GraphQL 中的定位GraphQL 用 Query 执行读取、用 Mutation 执行写入而Subscription 用于服务器向客户端持续推送数据变更。TypeGraphQL 原生支持订阅并借助graphql-subscriptionsApollo GraphQL 团队维护这一类 PubSub 实现完成事件的发布与订阅。在 0.16.0 版本中Subscription()装饰器、PubSub()参数装饰器与buildSchema的pubSub选项构成了完整的订阅链路src/decorators/Subscription.ts负责收集订阅元数据src/schema/schema-generator.ts负责把订阅元数据转换成 GraphQL 的subscribe字段运行期需要一个 PubSub 实例默认基于EventEmitter的进程内实现。订阅解析器的整体形态与 Query/Mutation 解析器 类似但多了一层监听主题 → 接收载荷 → 转换返回值的处理因此稍显复杂。二、创建第一个订阅解析器2.1 最小订阅Subscription 装饰器订阅解析器同样是一个普通类方法只是改用Subscription()装饰器标记class SampleResolver { // ... Subscription() newNotification(): Notification { // ... } }注意仅有Subscription()而没有提供主题时订阅只是声明了返回类型真正可运行还需要配合下面的topics或subscribe选项。2.2 指定订阅主题topics需要告诉 TypeGraphQL 我们要订阅哪些主题topics。topics支持三种形态同时推荐用 TypeScript 枚举提升类型安全参见examples/simple-subscriptions/pubsub.ts中export const enum Topic的用法class SampleResolver { // ... Subscription({ topics: NOTIFICATIONS, // 单个主题 topics: [NOTIFICATIONS, ERRORS] // 或主题数组 topics: ({ args, payload, context }) args.topic // 或动态主题函数 }) newNotification(): Notification { // ... } }单个主题字符串如NOTIFICATIONS订阅所有发布到该主题的事件主题数组同时监听多个主题。从源码看多个主题会通过Repeater.merge([...topics.map(topic pubSub.subscribe(topic, topicId))])合并成同一个异步迭代器src/schema/schema-generator.ts任一主题有事件都会触发解析器动态主题函数接收{ args, payload, context }即SubscribeResolverData包含source/args/context/info依据订阅查询参数动态决定主题典型场景如客户端传入想订阅的话题名。空数组校验Subscription({ topics: [] })会在装饰器求值阶段直接抛出MissingSubscriptionTopicsErrorsrc/decorators/Subscription.ts运行时若解析后主题仍为空数组src/schema/schema-generator.ts同样会抛出该错误保证不会出现静默的无效订阅。2.3 过滤事件filter并非主题上的每个事件都应该推送给订阅者。filter选项用于决定哪些事件触发订阅函数签名接收{ payload, args, context, info }必须返回boolean或Promisebooleanclass SampleResolver { // ... Subscription({ topics: NOTIFICATIONS, filter: ({ payload, args }) args.priorities.includes(payload.priority), }) newNotification(): Notification { // ... } }上述示例只有当载荷的priority出现在订阅参数priorities中时事件才会真正派发给该订阅者。底层实现中TypeGraphQL 用pipe(pubSubIterable, filter(payload ...))将过滤逻辑串入异步迭代流src/schema/schema-generator.ts因此过滤发生在订阅者的数据流内部而非发布端。2.4 接收载荷并转换返回值Root主题被触发后订阅解析器通过Root()装饰器接收来自 pubsub 的载荷payload并在方法体内把它转换为订阅字段要求的返回形状class SampleResolver { // ... Subscription({ topics: NOTIFICATIONS, filter: ({ payload, args }) args.priorities.includes(payload.priority), }) newNotification( Root() notificationPayload: NotificationPayload, Args() args: NewNotificationsArgs, ): Notification { return { ...notificationPayload, date: new Date(), }; } }在examples/simple-subscriptions/notification.resolver.ts中可以看到真实用法normalSubscription直接把NotificationPayload展开并补上date字段subscriptionWithFilter则演示了filter: ({ payload }) payload.id % 2 0的奇偶过滤。三、发布主题事件触发订阅的 pubsub3.1 pubsub 是什么上文一直在说触发主题触发动作来自pubsub发布/订阅系统。事件可能来自数据库的外部变更也可以在我们自己的 Mutation 中触发——比如修改了某个客户端关心的资源时发布通知。假设我们有这样一个添加评论的 Mutationclass SampleResolver { // ... Mutation(returns Boolean) async addNewComment(Arg(comment) input: CommentInput) { const comment this.commentsService.createNew(input); await this.commentsRepository.save(comment); return true; } }3.2 注入 PubSub 实例PubSub()使用PubSub()参数装饰器把pubsub注入到方法参数中即可在任意地方publish主题并广播载荷给所有订阅者class SampleResolver { // ... Mutation(returns Boolean) async addNewComment(Arg(comment) input: CommentInput, PubSub() pubSub: PubSubEngine) { const comment this.commentsService.createNew(input); await this.commentsRepository.save(comment); // 触发订阅主题 const payload: NotificationPayload { message: input.content }; await pubSub.publish(NOTIFICATIONS, payload); return true; } }调用pubSub.publish(NOTIFICATIONS, payload)后所有绑定到NOTIFICATIONS主题的订阅都会被触发。3.3 只注入 publishPubSub(TOPIC_NAME)为了便于测试更容易 mock/stub也可以只注入绑定到指定主题的publish方法配合PublisherTPayload类型class SampleResolver { // ... Mutation(returns Boolean) async addNewComment( Arg(comment) input: CommentInput, PubSub(NOTIFICATIONS) publish: PublisherNotificationPayload, ) { const comment this.commentsService.createNew(input); await this.commentsRepository.save(comment); // 触发订阅主题 await publish({ message: input.content }); return true; } }相比直接注入整个 PubSub 实例这种写法把发布到哪个主题的职责收拢到参数级别单测中只需 stub 一个publish函数即可无需构造完整 PubSub 引擎。至此执行addNewCommentMutation 时所有订阅了NOTIFICATIONS主题的 Subscription 都会被触发。3.4 发布端的实现细节在 0.16.0 时代的实现中publish是 PubSub 引擎的标准能力。仓库示例examples/simple-subscriptions/notification.resolver.ts展示了在 Mutation 中直接pubSub.publish(Topic.NOTIFICATIONS, payload)的完整链路而examples/simple-subscriptions/pubsub.ts中通过createPubSub{ [Topic.NOTIFICATIONS]: [NotificationPayload] }()预先声明了主题与载荷类型的映射让publish与subscribe在编译期就能得到类型检查。四、自定义 PubSub 系统从进程内到分布式4.1 默认实现的局限默认情况下TypeGraphQL 使用graphql-subscriptions中基于EventEmitter的简单PubSub。这种方案有一个显著缺陷只在 Node.js 应用为单实例单进程时才能正确工作——事件发生在进程 A进程 B 的订阅者完全收不到。4.2 接入外部存储的 PubSub 实现为了更好的可扩展性应选用由外部存储支撑的 PubSub 实现例如基于 Redis 的graphql-redis-subscriptions包。接入方式非常简单按包说明创建 PubSub 实例然后在buildSchema选项中传入即可const myRedisPubSub getConfiguredRedisPubSub(); const schema await buildSchema({ resolvers: [__dirname /**/*.resolver.ts], pubSub: myRedisPubSub, });buildSchema的pubSub选项是订阅功能的开关从源码看当存在订阅处理器而pubSub未提供时schema 生成阶段会抛出MissingPubSubErrorsrc/schema/schema-generator.ts防止生成一个无法工作的订阅 Schema。4.3 Redis 订阅的生产级示例仓库中的 redis-subscriptions 示例 演示了生产环境推荐方案。其pubsub.ts使用graphql-yoga/redis-event-target的createRedisEventTarget创建发布/订阅双客户端并配置了retryStrategy重连策略import { createRedisEventTarget } from graphql-yoga/redis-event-target; import { createPubSub } from graphql-yoga/subscription; import { Redis } from ioredis; const redisUrl process.env.REDIS_URL; if (!redisUrl) { throw new Error(REDIS_URL env variable is not defined); } export const pubSub createPubSub{ [Topic.NEW_COMMENT]: [NewCommentPayload]; }({ eventTarget: createRedisEventTarget({ publishClient: new Redis(redisUrl, { retryStrategy: times Math.max(times * 100, 3000), }), subscribeClient: new Redis(redisUrl, { retryStrategy: times Math.max(times * 100, 3000), }), }), });要点环境变量驱动示例要求设置REDIS_URL环境变量否则启动即报错双客户端模型发布客户端与订阅客户端分离避免 Redis 客户端在订阅模式下无法执行普通命令的问题重试策略retryStrategy让连接中断后按指数退避自动重连运行前提需要本地有运行中的 Redis 实例且可能需按实际连接参数修改示例代码。五、创建订阅服务端WebSocket 传输bootstrap 指南 与之前的示例都用apollo-server创建 GraphQL API 的 HTTP 端点。好消息是订阅不需要我们手动实现传输层。HTTP 无法做到真正的推送式通信订阅依赖 WebSocket而apollo-server内置了基于 WebSocket 的订阅支持开箱即用无需改动 bootstrap 配置。如果愿意也可以显式提供subscriptions配置项来定制路径与钩子// 创建 GraphQL server const server new ApolloServer({ schema, subscriptions: { path: /subscriptions, // 其他选项与钩子如 onConnect }, });完成之后我们就在/subscriptions路径上得到了一个可用的 GraphQL 订阅服务端同时保留原来的 HTTP GraphQL 服务端。六、从 0.16.0 到现代版本的订阅演进本文对应的文档版本0.16.0以graphql-subscriptionsPubSubEngine/Publisher类型为基础设施。仓库最新文档 docs/subscriptions.md 则展示了订阅 API 的演进PubSub 创建方式现代版本推荐createPubSub()来自graphql-yoga/subscription并支持用泛型声明主题与载荷类型映射createPubSub{ NOTIFICATIONS: [NotificationPayload] }()自定义 subscribe 逻辑新增subscribe选项可直接返回AsyncIterable或PromiseAsyncIterable例如对接 Prisma 订阅能力但不能与topics/filter混用动态主题 IDtopicId支持将主题限定到具体实体 ID如topicId: ({ context }) context.userId发布时以第二个参数传入 ID实现按实体隔离的事件流PubSub 接口约定任何 PubSub 系统只要满足publish(routingKey, ...args)与subscribe(routingKey, dynamicId?)两个方法即可接入见src/typings/subscriptions.ts导出的PubSub接口Apollo Server 3 之后apollo-server不再内置订阅支持需要按官方文档手动开启更现代的方案是使用graphql-yoga见 simple-subscriptions 示例 中createYoga的用法。七、端到端示例simple-subscriptions 全流程仓库的 simple-subscriptions 示例 是理解订阅全流程的最佳教材定义类型与载荷notification.type.ts声明Notification对外返回与NotificationPayload发布载荷创建 PubSub 并声明主题pubsub.ts中export const enum Topic定义主题常量createPubSub...()建立主题与载荷的类型映射编写订阅解析器notification.resolver.ts演示了无过滤订阅、filter过滤订阅、多主题订阅topics: [Topic.NOTIFICATIONS, NOTIFICATIONS_2]、基于参数动态主题topics: ({ args }) args.topic以及动态主题 IDtopicId五种订阅形态以及配套的pubSubMutation、publishToDynamicTopic、publishWithDynamicTopicId三个发布 Mutation启动服务index.ts中buildSchema({ resolvers: [NotificationResolver], pubSub })构建 Schema再用graphql-yoga的createYoga({ schema })创建同时支持 HTTP 与 WebSocket 的服务器。八、最佳实践小结用枚举管理主题把主题字符串收敛为const enum避免拼写错误同时获得类型提示过滤放在订阅端filter在订阅者的异步迭代器内部执行可按不同订阅参数各自过滤发布端只需广播全量事件发布端注入最小依赖用PubSub(TOPIC)注入绑定主题的publish便于单测 mock生产环境务必使用分布式 PubSub单进程 EventEmitter 在部署多实例时会丢失跨进程事件Redis 等外部存储是推荐方案确保buildSchema传入pubSub否则存在订阅时 schema 生成会抛出MissingPubSubError注意版本差异0.16.0 基于graphql-subscriptions现代版本基于graphql-yoga/subscription的createPubSub与PubSub接口迁移时需同步调整发布端代码与服务器配置Apollo Server 3 需手动启用订阅或改用 graphql-yoga。赞分享后端GraphQLAPI设计【免费下载链接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!项目地址https://gitcode.com/gh_mirrors/ty/type-graphql点击查看免费下载相关推荐mold 项目中的 Zstandard 测试体系从 CI 分层到调试节压缩的实战验证mold 项目中的 Zstandard 测试体系从 CI 分层到调试节压缩的实战验证 本文以 mold 仓库内置的 Zstandardzstd组件测试文档后端GraphQLAPI设计TypeGraphQL 订阅Subscriptions实战指南用装饰器构建实时 GraphQL 推送TypeGraphQL 订阅Subscriptions实战指南用装饰器构建实时 GraphQL 推送 GraphQL 标准定义了三种操作类型用 Quer后端GraphQLAPI设计GraphQL Yoga 订阅实战基于 examples/subscriptions 掌握 PubSub、Repeater 与 WebSocket 订阅全流程GraphQL Yoga 订阅实战基于 examples/subscriptions 掌握 PubSub、Repeater 与 WebSocket 订阅全流程后端API设计创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Linux内核驱动开发——动态加载驱动与platform
Linux内核驱动开发——动态加载驱动与platform

LKM(Linux Kernel Module)就是内核动态模块,不用重新编译烧录整个内核;在这个模块里面,代码不写死在设备树,而是代码里动态创建、注册 platform 设备。 组合起来 一个内核模块,加载 insmod 时在… · 2026/9/27 7:00:15

Qwen3-ASR 本地部署完全指南:环境搭建、FlashAttention 加速与常见问题避坑清单
Qwen3-ASR 本地部署完全指南:环境搭建、FlashAttention 加速与常见问题避坑清单

Qwen3-ASR 本地部署完全指南:环境搭建、FlashAttention 加速与常见问题避坑清单 【免费下载链接】Qwen3-ASR Qwen3-ASR is an open-source series of ASR models developed by the Qwen team at Alibaba Cloud, supporting stable multilingual speech/music/song recognition,… · 2026/9/27 7:00:15

凡科网站登录入口怎么选?3个细节避开黑产陷阱
凡科网站登录入口怎么选?3个细节避开黑产陷阱

凡科网站登录入口怎么选?3个细节避开黑产陷阱 你的网站是不是突然弹出了赌博广告,或者页面代码里莫名其妙多了几行JS?这时候别慌,90%的独立站长第一反应是“我被黑了”,但往往忽略了一个最基础的源头: 登录入口的安全设计… · 2026/9/27 7:00:09

网站被黑挂马急!从零搭建到做关键词优化的安全实战
网站被黑挂马急!从零搭建到做关键词优化的安全实战

网站被黑挂马急!从零搭建到做关键词优化的安全实战 你的服务器刚发出警报,页面弹出一堆乱七八糟的博彩广告,后台密码突然失效,这种 网站被黑挂马不知道怎么办… · 2026/9/27 7:37:52

交换机环路导致整网变慢:广播风暴的判据与定位处置步骤
交换机环路导致整网变慢:广播风暴的判据与定位处置步骤

「昨天还好好的,今天整个楼层都上不了网」,同时交换机指示灯整齐地高频闪烁——这类报修在二层网络里有一个高频成因:环路引发的广播风暴。它的特点是影响范围是整段广播域,且和网络出口、宽带带宽无关,用错排查方向会… · 2026/9/27 7:37:46

用智一刻3步选对论文选题工具,告别生搬硬套
用智一刻3步选对论文选题工具,告别生搬硬套

每年定开题报告时,很多同学都会被导师打上一句批注:“缺少理论分析工具,论文深度不够,像在写工作总结。” 为了交差,不少人开始到网上去搜理论,什么宏大战略管理理论、复杂系统演化模型统统往上套。结果开… · 2026/9/27 7:37:40

MySQL数据透视与多维数据分析技巧
MySQL数据透视与多维数据分析技巧

现代数据分析中,数据透视表和多维数据分析已经成为重要的工具。在数据库中直接进行数据透视和多维分析操作,不仅可以大幅提升效率,还可以减少数据导出和重复整理的工作量。MySQL 提供了数据透视表的基础实现与动态透视、多维数据分析的多种方式,适合在各类业务报表中应用。… · 2026/9/27 7:37:34

5招搞定wordpress显示文章id 新手入门避坑指南
5招搞定wordpress显示文章id 新手入门避坑指南

5招搞定wordpress显示文章id 新手入门避坑指南 网站被黑挂马不知道怎么办?这种惊魂时刻,很多新手站长都经历过。页面突然多出乱码广告,后台多出陌生管理员,浏览器地址栏弹出黄色警告。别慌,先深呼吸。这时候你需要做的不是盲目重装系统,而… · 2026/9/27 7:37:34

MySQL用户行为与销售数据分析
MySQL用户行为与销售数据分析

在数据驱动的商业环境中,理解客户行为与销售数据已成为推动业务发展的核心。通过分析用户行为数据和销售数据,可以识别用户模式、优化业务策略,从而促进客户转化和提升销售业绩。 本文旨在介绍如何使用MySQL分析用户行为数据和销售数据,帮助自学编程的读者掌握核心的SQL数… · 2026/9/27 7:37:34

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码