订阅 | Subscription

在 GraphQL 中,订阅(Subscription)允许服务端推送数据到客户端。

基础使用

GQLoom 中,我们使用 subscription 函数来定义一个订阅:

valibot
zod
import { weave, resolver, subscription } from "@gqloom/valibot" import * as v from "valibot" import { createServer } from "node:http" import { createYoga } from "graphql-yoga" const CountdownResolver = resolver({ countdown: subscription(v.number(), { input: { seconds: v.pipe(v.number(), v.integer()) }, subscribe: async function* (data) { for (let i = data.seconds; i >= 0; i--) { await new Promise((resolve) => setTimeout(resolve, 1000)) yield i } }, }), }) const schema = weave(CountdownResolver) const yoga = createYoga({ schema }) const server = createServer(yoga) server.listen(4000, () => { console.info("Server is running on http://localhost:4000/graphql") })

在上面的代码中,我们定义了一个 countdown 订阅,它接受一个 seconds 参数。 我们在订阅函数中传入了一个异步生成器,它会每秒推送一个数字,直到数字为 0。

使用发布/订阅

我们还可以使用 GraphQL Yoga 提供的发布/订阅(publish/subscribe)功能来更轻松地推送消息:

valibot
zod
import { resolver, query, subscription } from "@gqloom/valibot" import { createPubSub } from "graphql-yoga" import * as v from "valibot" const pubSub = createPubSub<{ greeting: [string] }>() const HelloResolver = resolver({ hello: query(v.string(), { input: { name: v.string() }, resolve: ({ name }) => { const hello = `Hello, ${name}` pubSub.publish("greeting", hello) return hello }, }), listenGreeting: subscription(v.string(), { subscribe: () => pubSub.subscribe("greeting"), resolve: (payload) => payload, }), })

在上面的代码中,我们定义了一个 hello 查询和一个 listenGreeting 订阅。 当 hello 查询被调用时,它会发布一个 greeting 事件,然后 listenGreeting 订阅会订阅这个事件,并在事件发生时推送消息。

你可以在 GraphQL Yoga 文档了解到发布/订阅功能的详细用法。

在分布式系统中使用订阅

订阅功能在单体应用中可以很轻松地工作。但在分布式系统中,订阅功能可能会变得复杂。你可以考虑使用来自 WunderGraph Cosmo事件驱动的联合订阅功能来处理分布式系统中的订阅。