订阅GraphQL Server时出错

我对GraphQl相当陌生,我在这里遵循GraphQL NodeJS后端教程: GraphQL实时订阅 。 一切运作良好,我完成了教程。 接下来我跟着阿波罗前端教程在这里VueJS: Vue&Apollo订阅 。 我从第一个教程中select使用自己创build的GraphQL服务器,而不是使用前端教程中使用的GraphCool。 这是我卡住的部分。 如果我打电话

subscription { Link(filter: { mutation_in: [CREATED] }) { node { id url description } } } 

在GraphiQL客户端中,当我使用数据data: Link: node: {id: "59ef0bbeef32bb05692ee4b4", url: "http://new-test-url2.com", description: "Test description2"}在不同的浏览器选项卡中创build一个新的链接时,我获得了idurldescription data: Link: node: {id: "59ef0bbeef32bb05692ee4b4", url: "http://new-test-url2.com", description: "Test description2"} (此订阅调用也在后端教程中进行)。 但是当我打电话

 subscription { Link(filter: { mutation_in: [CREATED] }) { node { id url description postedBy { id name } votes { id user { id } } } } } 

我得到的错误:

 {message: "Cannot destructure property `Users` of 'undefined' or 'null'.",…} {message: "Cannot destructure property `Votes` of 'undefined' or 'null'.",…} 

与数据data:{Link: {node: null}}

我只是找不到这个问题的答案。 希望有人能帮助我这个。 这是我的代码:

架构/ index.js

 type Link { id: ID! url: String! description: String! postedBy: User votes: [Vote!]! } type User { id: ID! name: String! email: String! password: String! votes: [Vote!]! } type Vote { id: ID! user: User! link: Link! } type SigninPayload { token: String user: User } type Query { allLinks(filter: LinkFilter, skip: Int, first: Int): [Link!]! } type Mutation { createLink(url: String!, description: String!): Link createVote(linkId: ID!): Vote createUser(name: String!, email: String!, password: String!): User signinUser(email: String!, password: String!): SigninPayload! } type Subscription { Link(filter: LinkSubscriptionFilter): LinkSubscriptionPayload Vote(filter: VoteSubscriptionFilter): VoteSubscriptionPayload } input LinkSubscriptionFilter { mutation_in: [_ModelMutationType!] } input VoteSubscriptionFilter { mutation_in: [_ModelMutationType!] } type LinkSubscriptionPayload { mutation: _ModelMutationType! node: Link } type VoteSubscriptionPayload { mutation: _ModelMutationType! node: Vote } input LinkFilter { OR: [LinkFilter!] description_contains: String url_contains: String } enum _ModelMutationType { CREATED UPDATED DELETED } 

架构/ resolvers.js:

 Query: { allLinks: async (root, {filter, first, skip}, {mongo: {Links, Users}}) => { let query = filter ? {$or: buildFilters(filter)} : {}; const cursor = Links.find(query); if (first) { cursor.limit(first); } if (skip) { cursor.skip(skip); } return cursor.toArray(); }, }, Mutation: { createLink: async (root, data, {mongo: {Links}, user}) => { assertValidLink(data); const newLink = Object.assign({postedById: user && user._id}, data); const response = await Links.insert(newLink); newLink.id = response.insertedIds[0]; pubsub.publish('Link', {Link: {mutation: 'CREATED', node: newLink}}); return newLink; }, createUser: async (root, data, {mongo: {Users}}) => { const newUser = { name: data.name, email: data.email, password: data.password, }; const response = await Users.insert(newUser); return Object.assign({id: response.insertedIds[0]}, newUser); }, createVote: async (root, data, {mongo: {Votes}, user}) => { const newVote = { userId: user && user._id, linkId: new ObjectID(data.linkId), }; const response = await Votes.insert(newVote); return Object.assign({id: response.insertedIds[0]}, newVote); }, signinUser: async (root, data, {mongo: {Users}}) => { const user = await Users.findOne({email: data.email}); if (data.password === user.password) { return { token: `token-${user.email}`, user }; } }, }, Subscription: { Link: { subscribe: () => pubsub.asyncIterator('Link'), }, }, Link: { id: root => root._id || root.id, // postedBy: async ({postedById}, data, {dataloaders: {userLoader}}) => { // return await userLoader.load(postedById); // }, postedBy: async ({postedById}, data, {mongo: {Users}}) => { return await Users.findOne({_id: postedById}); }, votes: async ({_id}, data, {mongo: {Votes}}) => { return await Votes.find({linkId: _id}).toArray(); }, }, 

希望你能解决这个问题,因为它已经这么久了,我自己今天就想出了这个。 这里的问题是,订阅服务器从来没有在上下文中传递,即dataloaders /用户信息。

在本课( https://www.howtographql.com/graphql-js/4-connectors/ )中,您为快速服务器设置了上下文,但是这个从未添加到订阅服务器:

  const buildOptions = async (req,res) => { const user = await authenticate(req, mongo.Users) return { context: { dataloaders: buildDataloaders(mongo), mongo, user }, formatError, schema, } 

为了将其添加到订阅服务器我自己使用这些选项:

 const subscriptionBuildOptions = async (connectionParams,webSocket) => { return { dataloaders: buildDataloaders(mongo), mongo, } } 

然后,我通过添加onConnect参数将其添加到SubscriptionServer:

 const server = createServer(app); server.listen(PORT, () => { SubscriptionServer.create( {execute, subscribe, schema, onConnect: subscriptionBuildOptions}, {server, path: '/subscriptions'}, ); console.log(`Hackernews GraphQL server running on port ${PORT}.`) }); 

这应该主要是让一切工作。 我个人正在做reactjs教程,所以不知道会有什么个别的问题,但reactjs教程API调用有点不同步。