使用Express-GraphQL和React-Apollo的GraphQL订阅
我已经遵循Apollo的文档来设置客户端和服务器上的GraphQL订阅,虽然我90%在那里,但我无法弄清楚如何设置订阅渠道以及如何将突变连接到这些渠道,以便每当发生突变时,服务器就会将新数据推送到客户端。 (关于内容,我正在制作一个Reddit克隆,人们发布主题和其他人发表评论,所以当你看到“主题”或“主题列表”时,将这些视为帖子。)使用Express-GraphQL和React-Apollo的GraphQL订阅
到目前为止,我已经设置了阿波罗客户端订阅成功:
const wsClient = new SubscriptionClient('ws://localhost:3001/subscriptions', {
reconnect: true
});
const networkInterface = createNetworkInterface({
uri: '/graphql',
opts: {
credentials: 'same-origin'
}
});
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
networkInterface,
wsClient,
);
const client = new ApolloClient({
networkInterface: networkInterfaceWithSubscriptions,
dataIdFromObject: o => o.id
});
而且我也为订阅设置了我的后端。这是我的server.js文件:
//===========================================================
//Subscription Managaer
//===========================================================
const pubsub = new PubSub();
const subscriptionManager = new SubscriptionManager({
schema: schema,
pubsub: pubsub
});
//=====================================
//WebSocket + Express Server
//=====================================
const server = createServer(app);
//setup listening port
server.listen(3001,()=>{
new SubscriptionServer(
{
subscriptionManager: subscriptionManager,
onConnect: (connectionParams, webSocket) => {
console.log('Websocket connection established');
},
onSubscribe: (message, params, webSocket) => {
console.log("The client has been subscribed", message, params);
},
onUnsubsribe: (webSocket) => {
console.log("Now unsubscribed");
},
onDisconnect: (webSocket) => {
console.log('Now disconnected');
}
},
{
server: server,
path: '/subscriptions',
});
console.log('Server is hot my man!');
})
我知道这些都是成功的,因为我得到记录在我的终端“WebSocket连接建立”消息。
接下来是实际认购 - 我已经创建了一个订阅模式类型(就像查询和突变):
const SubscriptionType = new GraphQLObjectType({
name: 'Subscription',
fields:() => ({
topicAdded: {
type: TopicType,
args: {repoFullName: {type: GraphQLString}}, //I don't understand what repoFullName is - I was trying to follow the Apollo docs, but they never specified that
resolve(parentValue, args){
return parentValue;
}
}
})
});
module.exports = SubscriptionType;
,并纳入我的根架构。所以,当我检查出GraphiQL,我看到:在文档侧菜单 My GraphiQIL UI showing the subscriptionSchema successfully
可用此订阅在我的阵营组成部分,我成功地利用Apollo的subscribeToMore法“订阅”它:
const TOPICS_SUBSCRIPTION = gql`
subscription OnTopicAdded($repoFullName: String){
topicAdded(repoFullName: $repoFullName){
id
}
}
`;
class TopicList extends Component {
componentDidMount() {
this.createMessageSubscription = this.props.data.subscribeToMore({
document: TOPICS_SUBSCRIPTION,
// updateQuery: (previousState, {subscriptionData}) => {
// const newTopic = subscriptionData.data.Topic.node
// const topics = previousState.findTopics.concat([newTopic])
// return {
// findTopics: topics
// }
// },
onError: (err) => console.error(err)
})
} //...
我让我的“客户端已订阅”消息登录到我的终端。但这是我卡住的地方。我已阅读了关于SubscriptionManager的SetupFunction,但未包含在Apollo的文档中。而且我无法找到如何将“createTopic”突变映射到此订阅,以便每当有人添加新主题时,它都会弹出到TopicList中。
我意识到这真的很漫长,但我一直在嘲笑我的头发,想弄清楚下一步是什么。任何帮助将非常感激!!感谢您的阅读!
是的,你缺少设置功能。你可以看看这个链接GraphQL subscription docu或这个example。
它应该如何工作: 首先,您需要发布已更改数据的渠道。你的情况可能是这样的:
const manager = new sub.SubscriptionManager({
schema,
pubSub,
setupFunctions: {
topicAdded: (options, args) => ({ // name of your graphQL subscription
topicAddedChannel: { // name of your pubsub publish-tag
filter: (topic) => {
console.log(topic); //should always show you the new topic if there is a subscribed client
return true; // You might want to add a filter. Maybe for guest users or so
},
},
}),
},
});
在这里你看到订阅的args: {repoFullName: {type: GraphQLString}}
参数的需要。如果您要过滤依赖于“repoName”的订阅。这意味着只有以“repoName”作为参数的订阅的客户才能获得更新。
接下来你需要一个地方,你可以调用pubsub.publish
函数。在你的情况下,添加主题突变通过后。看起来是这样的:
...
const topic = new Topic(/* args */);
topic.save((error, topic) => {
if (!error) {
pubsub.publish("topicAddedChannel", topic);
}
...
});
....
谢谢Locco0_0!但是我之前也尝试添加一个新的评论,我得到这个错误在控制台: 遗漏的类型错误:在WebSocket.client.onmessage 以及无法读取的不确定 财产“处理程序”: 参数无效返回从onSubscribe!返回值必须是一个对象!“ 有关更多的参考资料,现在我的addTopic突变(在codepen中,因为我无法在这里使用char限制):[link](https:// codepen。 io/bfitty/pen/jBoXda) 我仍然可以添加一个主题,但我必须按照惯例做,并刷新页面,让它显示在列表上。任何想法? –
订阅定义看起来不错, TopicType'定义了吗? 在你的情况下,你可以删除args参数,因为你没有你想传递给你的订阅的参数。编号 } } ;' 第一个错误对我来说并不是很清楚,但是您可以在'componentWillReceiveProps(newProps)'函数中添加订阅,并检查订阅查询是否已加载 –
而我刚刚在代码链接中看到您的设置一个新的pubsub()'。在这里你必须使用你添加到subscriptionManager的相同内容 –