使用 subscriptions-transport-ws 设置 Apollo 服务器?
Posted
技术标签:
【中文标题】使用 subscriptions-transport-ws 设置 Apollo 服务器?【英文标题】:Setting Up Apollo Server with subscriptions-transport-ws? 【发布时间】: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 连接失败:在收到握手响应之前连接已关闭
我错过了什么?
【问题讨论】:
【参考方案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',
,
);
【讨论】:
以上是关于使用 subscriptions-transport-ws 设置 Apollo 服务器?的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)