订阅 | Subscription
在 GraphQL 中,订阅(Subscription)允许服务端推送数据到客户端。
基础使用
在 GQLoom
中,我们使用 subscription
函数来定义一个订阅:
import { weave, resolver, subscription } from "@gqloom/core"
import { ValibotWeaver } 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)功能来更轻松地推送消息:
import { resolver, query, subscription } from "@gqloom/core"
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 的事件驱动的联合订阅功能来处理分布式系统中的订阅。