2017-09-25 82 views

回答

0

您将需要升级到Apollo 2.0。我最近做了write-up关于如何使用Apollo 2.0,因为官方文档尚未更新。

总之,你必须使用apollo-link现在客户端和executesubscribegraphql包现在就直接传递给SubscriptionServer代替。

你首先需要用正确的版本正确的包:如果你正在运行流星

npm install --save [email protected] [email protected] [email protected] [email protected] [email protected] graphql-subscriptions subscriptions-transport-ws apollo-server-express express graphql graphql-tools body-parser 

,您可能还需要:

meteor add apollo swydo:blaze-apollo swydo:graphql webapp 

现在的代码,以下是在Meteor中制作,但它可以很容易地适应其他服务器类型,例如Express。您也可以下载working example app

在客户端:

import { ApolloClient } from 'apollo-client'; 
import { ApolloLink } from 'apollo-link'; 
import { HttpLink } from 'apollo-link-http'; 
import WebSocketLink from 'apollo-link-ws'; 
import Cache from 'apollo-cache-inmemory'; 
import { getOperationAST } from 'graphql'; 

const httpUri = 'http://localhost:3000/graphql'; 
const wsUri = 'ws://localhost:3000/subscriptions'; 

const link = ApolloLink.split(
    operation => { 
    const operationAST = getOperationAST(operation.query, operation.operationName); 
    return !!operationAST && operationAST.operation === 'subscription'; 
    }, 
    new WebSocketLink({ 
    uri: wsUri, 
    options: { 
     reconnect: true, //auto-reconnect 
     // // carry login state (should use secure websockets (wss) when using this) 
     // connectionParams: { 
     // authToken: localStorage.getItem("Meteor.loginToken") 
     // } 
    } 
    }), 
    new HttpLink({ uri: httpUri }) 
); 

const cache = new Cache(window.__APOLLO_STATE); 

const client = new ApolloClient({ 
    link, 
    cache 
}); 

在服务器上:

import { WebApp } from 'meteor/webapp'; // Meteor-specific 
import { execute, subscribe } from 'graphql'; 
import { SubscriptionServer } from 'subscriptions-transport-ws'; 
import { createApolloServer, addCurrentUserToContext } from 'meteor/apollo'; // specific to Meteor, but you can always check out the Express implementation 
import { makeExecutableSchema } from 'graphql-tools'; 
import resolvers from './resolvers'; // your custom resolvers 
import typeDefs from './schema.graphql'; // your custom schema 

// make schema executable 
const schema = makeExecutableSchema({ 
    typeDefs, 
    resolvers 
}); 

// any additional context you use for your resolvers, if any 
const context = {}; 

// start a graphql server with Express handling a possible Meteor current user 
// if you're not using Meteor, check out https://github.com/apollographql/apollo-server for instructions on how to create a server in pure Node 
createApolloServer({ 
    schema, 
    context 
}, { 
    // // enable access to GraphQL API cross-domain (requires NPM "cors" package) 
    // configServer: expressServer => expressServer.use(cors()) 
}); 

// create subscription server 
// non-Meteor implementation here: https://github.com/apollographql/subscriptions-transport-ws 
new SubscriptionServer({ 
    schema, 
    execute, 
    subscribe, 
    // // on connect subscription lifecycle event 
    // onConnect: async (connectionParams, webSocket) => { 
    // // if a meteor login token is passed to the connection params from the client, 
    // // add the current user to the subscription context 
    // const subscriptionContext = connectionParams.authToken 
    //  ? await addCurrentUserToContext(context, connectionParams.authToken) 
    //  : context; 
    // return subscriptionContext; 
    // } 
}, { 
    server: WebApp.httpServer, 
    path: '/subscriptions' 
}); 

resolvers.js

import { withFilter } from 'graphql-subscriptions'; // will narrow down the changes subscriptions listen to 
import { PubSub } from 'graphql-subscriptions'; 
import { People } from '../imports/api/collections'; // Meteor-specific for doing database queries 

const pubsub = new PubSub(); 

const resolvers = { 

    Query: { 
    person(obj, args, context) { 
     const person = People.findOne(args.id); 
     if (person) { 
     // Mongo stores id as _id, but our GraphQL API calls for id, so make it conform to the API 
     person.id = person._id; 
     delete person._id; 
     } 
     return person; 
    } 
    }, 

    Mutation: { 
    updatePerson(obj, args, context) { 
     // You'll probably want to validate the args first in production, and possibly check user credentials using context 
     People.update({ _id: args.id }, { $set: { name: args.name, eyeColor: args.eyeColor, occupation: args.occupation } }); 
     pubsub.publish("personUpdated", { personUpdated: args }); // trigger a change to all subscriptions to this person 
     // Note: You must publish the object with the subscription name nested in the object! 
     // See: https://github.com/apollographql/graphql-subscriptions/issues/51 
     return args; 
    } 
    }, 

    Subscription: { 
    personUpdated: { 
     // See: https://github.com/apollographql/graphql-subscriptions#channels-mapping 
     // Take a look at "Channels Mapping" for handling multiple create, update, delete events 
     // Also, check out "PubSub Implementations" for using Redis instead of PubSub 
     // PubSub is not recommended for production because it won't work if you have multiple servers 
     // withFilter makes it so you can only listen to changes to this person instead of all people 
     subscribe: withFilter(() => pubsub.asyncIterator('personUpdated'), (payload, args) => { 
     return (payload.personUpdated.id===args.id); 
     }) 
    } 
    } 

}; 

export default resolvers; 

schema.graphql

enum EyeColor { 
    brown 
    blue 
    green 
    hazel 
} 

type Person { 
    id: ID 
    name: String 
    eyeColor: EyeColor 
    occupation: String 
} 

type Query { 
    person(id: ID!): Person 
} 

type Mutation { 
    updatePerson(id: ID!, name: String!, eyeColor: EyeColor!, occupation: String!): Person 
} 

type Subscription { 
    personUpdated(id: ID!): Person 
} 

schema { 
    query: Query 
    mutation: Mutation 
    subscription: Subscription 
} 

关于此问题的完整介绍可以在这篇文章中找到:How to get Apollo 2.0 working with GraphQL + subscriptions

一个示例应用程序演示如何使用阿波罗2.0与GraphQL服务器+订阅可以在这里找到:meteor-apollo2