GraphQL 是一个先进的 API 查询语言和运行时,它可以让开发者按需获取并组合他们需要的数据。GraphQL 的优势在于可以大大减少数据传输的冗余,提升 API 的性能和用户体验。但是传统的 GraphQL API 只能查询,不能订阅。为了解决这个痛点,GraphQL 新增了订阅操作,让开发者可以订阅数据的变化,实时获取最新的数据。
1. 订阅操作简介
GraphQL 的订阅操作是一种非常新颖的操作,它允许开发者可以订阅一个数据源的变化,并且在数据源发生变化时,能够及时地推送数据到客户端。这种操作非常适合于实时数据的场景,如实时聊天、在线协作等。
GraphQL 订阅操作的语法如下:
subscription { subscriptionName(arg1: String, arg2: Int) { field1 field2 # ... } }
上述语法中,subscription
关键字指定了这是一个订阅操作。subscriptionName
是订阅的名称,可以带上参数。field1
、field2
是订阅的字段。
2. 如何实现订阅操作?
GraphQL 的订阅操作可以通过一些库或框架来实现。本文将以 Apollo Server 为例来演示如何实现 GraphQL 的订阅操作。
2.1 安装 Apollo Server
npm i apollo-server
2.2 创建 Apollo Server
// javascriptcn.com 代码示例 const { ApolloServer, gql } = require('apollo-server') const typeDefs = gql` type Query { hello: String } type Subscription { message: String } ` const resolvers = { Query: { hello: () => 'Hello World' }, Subscription: { message: { subscribe: () => { // TODO: 实现订阅逻辑 } } } } const server = new ApolloServer({ typeDefs, resolvers }) server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`) })
以上代码中定义了一个 Query
类型,其中包含一个 hello
字段,它的值为字符串 "Hello World"
。同时定义了一个 Subscription
类型,其中包含一个 message
字段,它可以被订阅。
在 resolvers
中实现了 hello
字段的解析方法,它会返回一个字符串。在 resolvers
中还实现了 message
字段的 subscribe
方法,该方法会返回一个可观察对象。
2.3 实现订阅逻辑
在 Subscription
类型中定义的 message
字段,需要有一个 subscribe
函数来处理订阅逻辑。该函数需要返回一个可观察对象,用于推送数据。
在 Apollo Server 中,我们可以使用 PubSub
类来实现订阅逻辑。PubSub
是一个发布订阅模式的实现类,它能够和 GraphQL 的订阅操作很好地集成在一起。
// javascriptcn.com 代码示例 const { ApolloServer, gql, PubSub } = require('apollo-server') const pubsub = new PubSub() const resolvers = { Subscription: { message: { subscribe: () => pubsub.asyncIterator('NEW_MESSAGE') } }, Mutation: { postMessage: (_, { message }) => { pubsub.publish('NEW_MESSAGE', { message }) return true } } }
上面代码中,在 GraphQL Schema
中定义了一个 Mutation
类型,并实现了一个 postMessage
字段。当 postMessage
字段被调用时,它会调用 pubsub.publish
方法,该方法会发送一条消息给所有订阅了 NEW_MESSAGE
主题的客户端。
在 Subscription
类型中,我们使用 apollo-server
中提供的 asyncIterator
方法来返回一个可观察对象,该对象会监听 NEW_MESSAGE
主题的变化,一旦有新的消息到来,就会将消息推送给客户端。
2.4 订阅操作的实现及使用
我们使用 apollo-server
提供的工具 graphql-ws
来实现订阅操作的推送功能。
// javascriptcn.com 代码示例 const { ApolloServer } = require('apollo-server') const { execute, subscribe } = require('graphql') const { createServer } = require('http') const { SubscriptionServer } = require('subscriptions-transport-ws') const server = new ApolloServer({ /* ... */ }) server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`) SubscriptionServer.create( { execute, subscribe, schema: server.schema, }, { server: createServer(server.getRequestHandler()), path: server.graphqlPath, } ) })
使用 SubscriptionServer.create
方法创建一个订阅服务,该服务将 GraphQL 的执行和订阅设置成 WebSocket 的方式。
在客户端中,我们可以使用 subscriptions-transport-ws
工具来实现订阅操作的传输。
// javascriptcn.com 代码示例 import { SubscriptionClient } from 'subscriptions-transport-ws' import gql from 'graphql-tag' const subscriptionClient = new SubscriptionClient(`ws://localhost:4000/graphql`, { reconnect: true }) subscriptionClient.subscribe({ query: gql` subscription { message } `, variables: {}, operationName: 'message' }).subscribe({ next: (data) => console.log(data), error: (error) => console.error(error) })
以上代码实现了一个 message
字段的订阅操作,并输出了它的数据内容。客户端连接到 ws://localhost:4000/graphql
的 WebSocket 服务器,发送订阅请求,并通过 subscription.next(callback)
来接收数据。
3. 总结
从本文中我们了解到 GraphQL 的订阅操作是一种有效地提供实时数据的方法,使用 Apollo Server 和 PubSub
类我们可以很方便地实现订阅操作。如果你正在构建一个需要实时数据的应用,那么 GraphQL 的订阅操作是一个非常好的选择。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653718087d4982a6ebf6db4d