GraphQL 是新一代 API 技术,它能提高前端和后端之间的数据交互效率,让 Web 服务开发变得更加容易和快速。其中,GraphQL 的 Subscription 特性是一项重要的功能,它允许前端实时订阅后端数据的变化,重新定义了数据交互的方式。本文将为大家讲解 GraphQL 中的订阅(Subscription)实例教程,通过详细的案例,帮助大家深入学习和掌握该功能的使用方法。
什么是 GraphQL Subscription?
GraphQL Subscription 是 GraphQL 的一项实时数据查询功能,通过 Subscription,前端可以实时订阅后端的数据变化,当后端数据发生变化时,前端能立即收到推送消息。这与传统的轮询方式相比,可以提高数据交互效率,减少无效请求,使 Web 应用更加流畅和响应式。
要使用 GraphQL Subscription,需要实现一个 Subscription Type,该类型包含一个订阅器(resolver function),在服务器端将新的数据推送给客户端。同时,前端也需要定义一个 Subscription Query,通过这个 Subscription Query 可以实时订阅后端数据的变化。
GraphQL Subscription 的使用示例
接下来,我们将通过一个具有实际意义的示例,讲解 GraphQL Subscription 的使用方法。
在本示例中,我们将使用一个具有实时性需求的聊天室,用户可以在该聊天室发送消息,同时能实时接收到其他用户发送的消息。以下是该示例实现的步骤:
1. 定义 GraphQL Schema
首先,我们需要定义 GraphQL Schema,用于描述我们要实现的数据模型和订阅功能。在该示例中,我们需要定义两个类型:Message 和 Subscription,其中 Message 类型用于描述聊天室中的消息,Subscription 类型用于实现消息推送功能。以下是该 Schema 的实现代码:
---- ------- - --- --- -------- ------- ----- ------- - ---- ------------ - ----------- -------- - ---- ----- - --------- ----------- -
以上代码实现了 Message、Subscription、Query 三种类型,其中:
- Message 类型定义了消息的 id、content 和 user;
- Subscription 类型定义了名为 newMessage 的订阅器,该订阅器用于在有新消息时,通过指定的 resolver function,将新消息推送给客户端;
- Query 类型定义了名为 messages 的查询,该查询返回所有之前发送的消息。
以上代码示例中,在 Subscription 类型中定义了一个叫做 newMessage 的订阅器,在客户端订阅该订阅器时,服务端将在有新消息时通过订阅器返回该消息的详细信息。
2. 实现 Resolver Function
接下来,我们需要实现 Resolver Function,用于处理客户端的查询和订阅请求,我们需要实现如下四种 Resolver Function:
- Query resolver:用于处理客户端的普通查询请求;
- Subscription resolver:用于在有新消息时,将消息详细信息推送给客户端;
- Mutation resolver:用于处理客户端的修改请求,例如发送新的消息;
- Resolver for Message type:用于定义 Message 类型的数据获取方式。
在本示例中,我们需要实现两个 Resolver Function:
----- --------- - - ------ - --------- -- -- -------- -- ------------- - ----------- - ---------- -- -- --------------------------------------- - - -
以上代码中,我们定义了两个 Resolver Function,分别用于 Query 和 Subscription 类型:
- Query 类型的 Resolver 函数 messages,将返回所有消息;
- Subscription 类型的 Resolver 函数 newMessage,用于处理订阅请求,将返回在 NEW_MESSAGE_TOPIC 上注册的 resolver function。
3. 集成 pubsub
对于 Subscription resolver,我们需要使用 pubsub 来实现订阅功能,该功能需要与底层的 pubsub 库进行集成,以便可以在后端推送新的消息。
在本示例中,我们将使用 Node.js 的 Redis 库提供的 pubsub 库,实现订阅功能。以下是集成 pubsub 的代码实现:
-- -- ----- - ----- ----- - ------------------- -- ---- ------- -- ----- ------ - --- -------- -- ---- ----- -- ----- ----------------- - ------------- -- - -------- -------- ------ ----- -------- ------------------- - -------- ---- -- - ------ -- - ----- ------- - - --- --------------- - -- -------- ---- -- ----------------------- ----- --------------------------------- - ----------- ------- --- ------ -------- - -- -- -------- --- ------ ----- -------- - ---- ---- -------- - -------------------- -------- ----- --------- -------- - -- -- -- -------- -------- ----- --------- - - --------- - ----------- - --
以上代码实现了以下功能:
- 通过 Redis 提供的 pubsub 库创建 pubsub 实例;
- 定义订阅 Topic 名称 NEW_MESSAGE_TOPIC;
- 在 Mutation resolver 中通过 pubsub 实例,将新消息发布到 NEW_MESSAGE_TOPIC 上;
- 在 Mutation resolver 中定义 mutation 函数 sendMessage 用于发布新的消息。
4. 客户端订阅实例
最后,我们需要实现客户端的订阅功能,以便通过 Subscription 获取到服务端推送的消息。以下是客户端订阅的实现代码:
----- ------------------------ - ---- ------------ - ---------- - -- ---- ------- - - -- -------- ---------- - ----- ---------- ------------ - ------------- ----- ------------- - ----------------------------------- ----- - ----- ---------- - - ---------------- ------------------------ -- ------------ -- - ------------------------- ------------------------ -- -------------- ----- ---------------- - ----- ------- -- - ----------------------- ----- ------------- ---------- - -------- -------- ----- -------- - --- -- -- ------ ------- ----- ----- ----- ---- -
以上示例代码实现了如下功能:
- 定义名为 NEW_MESSAGE_SUBSCRIPTION 的 GraphQL Subscription Query;
- 使用 useSubscription Hook 订阅 NEW_MESSAGE_SUBSCRIPTION;
- 定义 handleNewMessage 函数用于发送消息;
- render 消息列表和发送消息的表单。
在客户端订阅 NEW_MESSAGE_SUBSCRIPTION Topic 后,当服务端有新消息时,客户端会立即收到推送消息,从而更新聊天记录。
结论
通过以上示例,我们可以看到 GraphQL Subscription 能够实现前端对后端数据的实时订阅,实现了推送式的数据更新,带来了更流畅、更实时的 Web 体验,同时也能减少无效数据交互和浪费的资源。以上示例也提供了一个实际项目的应用,对于进一步学习 GraphQL 技术和实现实时 Web 应用具有指导意义。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/67136ef8ad1e889fe20cdf8b