2017-04-06 95 views
1

我已經遵循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中。

我意識到這真的很漫長,但我一直在嘲笑我的頭髮,想弄清楚下一步是什麼。任何幫助將非常感激!!感謝您的閱讀!

回答

0

是的,你缺少設置功能。你可以看看這個鏈接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); 
 
    } 
 
    ... 
 
}); 
 

 

 
....

+0

謝謝Locco0_0!但是我之前也嘗試添加一個新的評論,我得到這個錯誤在控制檯: 遺漏的類型錯誤:在WebSocket.client.onmessage 以及無法讀取的不確定 財產「處理程序」: 參數無效返回從onSubscribe!返回值必須是一個對象!「 有關更多的參考資料,現在我的addTopic突變(在codepen中,因爲我無法在這裏使用char限制):[link](https:// codepen。 io/bfitty/pen/jBoXda) 我仍然可以添加一個主題,但我必須按照慣例做,並刷新頁面,讓它顯示在列表上。任何想法? –

+0

訂閱定義看起來不錯, TopicType'定義了嗎? 在你的情況下,你可以刪除args參數,因爲你沒有你想傳遞給你的訂閱的參數。編號 } } ;' 第一個錯誤對我來說並不是很清楚,但是您可以在'componentWillReceiveProps(newProps)'函數中添加訂閱,並檢查訂閱查詢是否已加載 –

+0

而我剛剛在代碼鏈接中看到您的設置一個新的pubsub()'。在這裏你必須使用你添加到subscriptionManager的相同內容 –