前言
在现代 Web 应用中,实时通知推送已经成为了一个必要功能。而实时通知的实现方式也有很多种,比如轮询、长轮询、SSE、WebSockets 等。其中,WebSockets 是一个可靠性高、效率高、易于使用的实时通信协议,已经被广泛应用于实时通知推送。
GraphQL 是一种用于 API 的查询语言,它可以在单个 API 请求中获取多个资源,并且可以精确控制返回的数据。而结合 WebSockets,我们可以在 GraphQL API 中实现实时通知推送的功能,让 Web 应用更加智能、高效、优雅。
本文将详细介绍如何使用 GraphQL + WebSockets 实现实时通知推送,并提供示例代码。
GraphQL Subscription
GraphQL Subscription 是 GraphQL 规范中定义的一种类型,它允许客户端通过订阅来接收实时数据更新。而 Subscription 的实现需要使用到 WebSockets。
下面是一个 GraphQL Subscription 的示例:
type Subscription { messageAdded(channelId: ID!): Message }
上面的代码定义了一个 Subscription 类型,它包含一个 messageAdded 订阅。当有新的消息添加到指定 channelId 的频道中时,服务器会向所有已订阅该频道的客户端推送新的消息数据。
WebSocket Server
在 Node.js 中,我们可以使用 ws 库来创建 WebSocket 服务器。下面是一个简单的 WebSocket 服务器示例:
// javascriptcn.com 代码示例 const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', function connection(ws) { console.log('Client connected'); ws.on('message', function incoming(message) { console.log(`Received message: ${message}`); ws.send(`You sent: ${message}`); }); ws.on('close', function close() { console.log('Client disconnected'); }); });
上面的代码创建了一个 WebSocket 服务器,监听 8080 端口。当客户端连接时,服务器会输出 Client connected。当客户端发送消息时,服务器会输出 Received message: xxx,并将消息原样返回给客户端。当客户端断开连接时,服务器会输出 Client disconnected。
GraphQL WebSocket Server
结合上面两个示例,我们可以创建一个 GraphQL WebSocket 服务器,用于处理 GraphQL Subscription 的订阅请求。
我们可以使用 graphql-ws 库来创建 GraphQL WebSocket 服务器。下面是一个简单的 GraphQL WebSocket 服务器示例:
// javascriptcn.com 代码示例 const { createServer } = require('http'); const { execute, subscribe } = require('graphql'); const { SubscriptionServer } = require('subscriptions-transport-ws'); const { makeExecutableSchema } = require('@graphql-tools/schema'); const { GraphQLScalarType } = require('graphql'); const { Kind } = require('graphql/language'); const WebSocket = require('ws'); // Define GraphQL schema const typeDefs = ` scalar Date type Message { id: ID! text: String! createdAt: Date! } type Subscription { messageAdded(channelId: ID!): Message } `; const resolvers = { Date: new GraphQLScalarType({ name: 'Date', description: 'Date custom scalar type', parseValue(value) { return new Date(value); }, serialize(value) { return value.getTime(); }, parseLiteral(ast) { if (ast.kind === Kind.INT) { return new Date(parseInt(ast.value, 10)); } return null; }, }), Subscription: { messageAdded: { subscribe: async (_, { channelId }, { pubsub }) => { const asyncIterator = pubsub.asyncIterator(`channel_${channelId}`); return asyncIterator; }, }, }, }; const schema = makeExecutableSchema({ typeDefs, resolvers }); // Create HTTP server const server = createServer((request, response) => { response.writeHead(404); response.end(); }); // Create WebSocket server const wsServer = new WebSocket.Server({ noServer: true }); // Create SubscriptionServer const subscriptionServer = SubscriptionServer.create( { schema, execute, subscribe, }, { server: wsServer, path: '/graphql', } ); // Handle WebSocket upgrade request server.on('upgrade', (request, socket, head) => { wsServer.handleUpgrade(request, socket, head, (socket) => { subscriptionServer._onWebSocketConnection(socket, request); }); }); // Start server server.listen(8080, () => { console.log(`Server started on port ${server.address().port}`); });
上面的代码创建了一个 GraphQL WebSocket 服务器,它包含一个 messageAdded 订阅。当有新的消息添加到指定 channelId 的频道中时,服务器会向所有已订阅该频道的客户端推送新的消息数据。
GraphQL WebSocket Client
在客户端,我们可以使用 graphql-ws 库来连接到 GraphQL WebSocket 服务器,并订阅 GraphQL Subscription。
下面是一个简单的 GraphQL WebSocket 客户端示例:
// javascriptcn.com 代码示例 import { WebSocketLink } from '@apollo/client/link/ws'; import { ApolloClient, InMemoryCache, gql } from '@apollo/client'; // Create WebSocketLink const link = new WebSocketLink({ uri: 'ws://localhost:8080/graphql', options: { reconnect: true, }, }); // Create ApolloClient const client = new ApolloClient({ link, cache: new InMemoryCache(), }); // Subscribe to GraphQL Subscription const subscription = client.subscribe({ query: gql` subscription { messageAdded(channelId: "1") { id text createdAt } } `, }); // Handle subscription data subscription.subscribe({ next(data) { console.log('Received data: ', data); }, error(error) { console.error('Subscription error: ', error); }, complete() { console.log('Subscription completed'); }, });
上面的代码创建了一个 ApolloClient,连接到了 GraphQL WebSocket 服务器。然后,它订阅了一个 messageAdded 订阅,并处理订阅数据的输出。
总结
本文介绍了如何使用 GraphQL + WebSockets 实现实时通知推送的功能,并提供了示例代码。通过结合 GraphQL 和 WebSockets,我们可以实现更加智能、高效、优雅的 Web 应用,提升用户体验和开发效率。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/655c603ed2f5e1655d67a6d8