javascript - 如何创建基本客户端以通过 websockets 使用 GraphQL 订阅

标签 javascript websocket graphql apollo-server graphql-subscriptions

我正在尝试创建一个基本的类似聊天的应用程序,只是为了学习一些东西。

我已经设置了一个基本的 graphql 服务器来处理连接用户,并让他们添加消息。现在我正在尝试添加一些机制,以便每个用户都可以实时看到彼此添加的消息。我是 GraphQL 新手,但我应该使用订阅。

这是我的服务器index.ts:

import { createServer } from 'http';
import jwt from 'jsonwebtoken';
import mongoose from 'mongoose';
import resolvers from 'modules/resolvers';
import typeDefs from 'modules/type-defs';
import { ApolloServer } from 'apollo-server-express';
import cookieParser from 'cookie-parser';
import express from 'express';
import cors from 'cors';

const PORT = 4000;

const getUser = (token: string) => {
  // ...
};

const server = new ApolloServer({
  context: ({ req, res }) => {
    const token = req.cookies.jwt;
    const currentUser = getUser(token);

    return { currentUser, req, res };
  },
  resolvers,
  subscriptions: {
    onConnect: async (connectionParams, webSocket, context) => {
      console.log(`Subscription client connected using Apollo server's built-in SubscriptionServer.`)
    },
    onDisconnect: async (webSocket, context) => {
      console.log(`Subscription client disconnected.`)
    },
  },
  typeDefs,
});

const app = express();
const httpServer = createServer(app);

app.use(cors({ credentials: true, origin: 'http://localhost:3000' }));
app.use(cookieParser());

server.applyMiddleware({ app, cors: false });
server.installSubscriptionHandlers(httpServer);

httpServer.listen(PORT, () => {
  console.log(`Server ready at http://localhost:${PORT}${server.graphqlPath}`);
  console.log(`Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`);
});

mongoose.connect('mongodb://127.0.0.1:27017/irc', {
  useCreateIndex: true,
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

我想做的是在客户端(javascript/react)设置尽可能简单的东西,而不必依赖像 apollo-client 这样的库。 我设法使用简单的获取调用来发送查询/突变,并期望也能够以“简单”的方式使用订阅。 Apollo-client 对于我想要做的事情来说似乎过于复杂,我想了解它实际上是如何工作的 - 但每个关于订阅的教程似乎都使用这个库......

我不太明白我的服务器在订阅方面实际上做了什么,我以为我已将其配置为监听 websockets 连接,但我不再那么确定了。

我尝试发送一条基本消息只是为了看看会发生什么:

const ws = new WebSocket('ws://localhost:4000/graphql');$
ws.onopen = event => {
  ws.send('Lorem ipsum dolor sit amet.');
};

...但即使我的 chrome 网络选项卡似乎表明一切正常,我的服务器似乎并不关心我的消息,因为没有记录任何内容。

有人可以解释一下是否可以使用基本的网络套接字来使用 apollo-server 的订阅吗?又如何?

谢谢

最佳答案

Apollo 服务器和 Apollo 客户端均使用 subscriptions-transport-ws在后台处理订阅。 subscriptions-transport-ws 使用 WebSocket 作为服务器和客户端之间交换消息的传输方式。这些消息具有库使用的特定格式 - 为了在客户端仅使用 WebSocket,您必须发送相同类型的消息。

您可以检查源代码以确定发送的消息类型以及发送时间。不过,更好的选择是创建 SubscriptionClient 的实例。并运用其方法。由于该库的使用没有特别详细的记录,因此您必须摸索着使用,但这应该是可能的。

如果您是 GraphQL 新手,那么您应该坚持使用 Apollo Client,因为它的文档相当不错(请参阅 here ),并且订阅的设置可能非常复杂,尤其是在添加身份验证后。

关于javascript - 如何创建基本客户端以通过 websockets 使用 GraphQL 订阅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60724612/

相关文章:

wordpress - 如何在 Gatsby 中获取所有 WordPress 帖子并显示标签

javascript - GatsbyJS 如何使用 GraphQL 获取 Markdown 文件并在特定页面上显示数据

javascript - 在 for 循环中使用 Model.create() 和 save()

javascript - jQuery 在两个以上类之间切换

javascript - 扭曲的 websocket 聊天服务器 openid 身份验证

http - SecureSocket 支持哪些协议(protocol)?

javascript - elasticlunr.js 不显示搜索查询结果

javascript - 如何包装来自第三方 api 的错误?

java - 尝试访问 websocket 时出现错误 404

swift - 如何在 graphQL 中编写 JOIN 或从多种类型获取结果 - AWS Appsync iOS