【问题标题】:Setting Up Apollo Server with subscriptions-transport-ws?使用 subscriptions-transport-ws 设置 Apollo 服务器?
【发布时间】:2017-02-07 11:55:24
【问题描述】:

我的服务器似乎是根据http://dev.apollodata.com/tools/apollo-server/setup.html 的 Apollo 文档设置的。在我的 server/main.js 文件中:

//SET UP APOLLO INCLUDING APOLLO PUBSUB
const executableSchema = makeExecutableSchema({
    typeDefs: Schema,
    resolvers: Resolvers,
    connectors: Connectors,
    logger: console,
});

const GRAPHQL_PORT = 8080;
const graphQLServer = express();

// `context` must be an object and can't be undefined when using connectors
graphQLServer.use('/graphql', bodyParser.json(), apolloExpress({
    schema: executableSchema,
    context: {}, //at least(!) an empty object
}));

graphQLServer.use('/graphiql', graphiqlExpress({
    endpointURL: '/graphql',
}));

graphQLServer.listen(GRAPHQL_PORT, () => console.log(
    `GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}/graphql`
));
//SET UP APOLLO INCLUDING APOLLO PUBSUB

它在终端日志中打印出“GraphQL Server is now running on http://localhost:8080/graphql”,表明服务器已成功初始化。

但是在我的 main_layout 组件的顶部,当我运行这段代码时:

import { Client } from 'subscriptions-transport-ws';
const wsClient = new Client('ws://localhost:8080');

...我收到此控制台消息:

到 'ws://localhost:8080/' 的 WebSocket 连接失败:在收到握手响应之前连接已关闭

我错过了什么?

【问题讨论】:

    标签: apollo apollo-server apollostack


    【解决方案1】:

    您需要创建一个专用的 websocket 服务器。它将在不同的端口上运行,设置它的代码在 subscriptions-transport-ws 包中提供。

    查看 GitHunt-API 示例中的以下代码: https://github.com/apollostack/GitHunt-API/blob/master/api/index.js#L101-L134

    您还会看到此代码依赖于一个名为 SubscriptionManager 的类。它是来自 apollo 团队的 graphql-subscriptions 包中的一个类,您可以在此处找到如何使用它的示例: https://github.com/apollostack/GitHunt-API/blob/master/api/subscriptions.js

    【讨论】:

    • 您在 GitHunt-API/api/index.js 中突出显示的代码没有引用架构,Apollo 文档说在设置服务器时必须引用架构。该模式在第 66 行突出显示的代码上方引用,但这是针对不同端口上的侦听器,该端口似乎主要与 GitHub API 相关。说我需要修改 3010 端口代码以省略对 GitHub 的引用是否正确?
    • 如果您想设置订阅(就像现在一样),您需要一个模式对象,该对象将提供给 SubscriptionManager 构造函数(我在答案的最后一部分中已经指出)和反过来,它将从 subscriptions-transport-ws 包中提供给 Server 类。它上面的参考与仅服务于突变和查询的 GraphQL POST 端点有关。完成所有这些配置后,您将在不同端口上留下两台服务器,一台用于 GraphQL 端点,另一台用于 websocket 以将事件推送到客户端。
    • 不需要专用的 websocket 端口 - 请参阅我的答案。
    【解决方案2】:

    这是一个关于使用 Apollo GraphQL、React 和 Hapi 的演示:https://github.com/evolastech/todo-react。它不像 GitHunt-React 和 GitHunt-API 那样不堪重负

    【讨论】:

      【解决方案3】:

      TL;DR:您可以使用graphql-up 快速获取支持订阅并准备就绪的 GraphQL 服务器。这里有更多 detailed tutorial 将其与 Apollo 和 websocket 客户端 subscriptions-transport-ws 结合使用。

      一键获取GraphQL Server

      假设您要基于此GraphQL Schema in IDL syntax 构建 Twitter 克隆:

      type Tweet {
        id: ID!
        title: String!
        author: User! @relation(name: "Tweets")
      }
      
      type User {
        id: ID!
        name: String!
        tweets: [Tweet!]! @relation(name: "Tweets")
      }
      

      单击此按钮接收您自己的 GraphQL API,然后打开 Playground,您可以在其中添加一些推文、查询所有推文并测试订阅。

      简单易用的 API

      首先,让我们创建一个用户,它将成为所有即将发布的推文的作者。在 Playground 中运行这个突变:

      mutation createUser {
        createUser(name: "Tweety") {
          id # copy this id for future mutations!
        }
      }
      

      以下是查询存储在 GraphQL 服务器上的所有推文及其作者的方法:

      query allTweets {
        allTweets {
          id
          title
          createdAt
          author {
            id
            name
          }
        }
      }
      

      使用 websocket 的订阅支持

      现在让我们订阅来自“Tweety”的新推文。这是语法:

      subscription createdTweets {
        Message(filter: {
          mutation_in: [CREATED]
          node: {
            author: {
              name: "Tweety"
            }
          }
        }) {
          node {
            id
            text
            createdAt
            sentBy {
              id
              name
            }
          }
        }
      }
      

      现在在 Playground 中创建一个新选项卡并创建一条新推文:

      mutation createTweet {
        createTweet(
          title: "#GraphQL Subscriptions are awesome!"
          authorId: "<id-from-above>"
        ) {
          id
        }
      }
      

      您应该会在您之前订阅的其他标签中看到一个新事件弹出。

      【讨论】:

        【解决方案4】:

        似乎您实际上并没有制作 websocket 服务器。使用订阅服务器。请记住,正如 davidyaha 所说,您必须拥有一个专用的 websocket 端口(我也曾想过)绝对不是真的。我的普通查询和订阅都在同一个端口上。

        import { createServer } from 'http';
        import { SubscriptionServer } from 'subscriptions-transport-ws';
        import { execute, subscribe } from 'graphql';
        import { schema } from './my-schema';
        
        // All your graphQLServer.use() etc setup goes here, MINUS the graphQLServer.listen(),
        // you'll do that with websocketServer:
        
        // Create WebSocket listener server
        const websocketServer = createServer(graphQLServer);
        
        // Bind it to port and start listening
        websocketServer.listen(3000, () => console.log(
          `Server is now running on http://localhost:3000`
        ));
        
        const subscriptionServer = SubscriptionServer.create(
          {
            schema,
            execute,
            subscribe,
          },
          {
            server: websocketServer,
            path: '/subscriptions',
          },
        );
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-05-11
          • 2018-02-11
          • 2023-02-25
          • 2020-03-29
          • 2019-04-27
          • 2020-05-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多