[英]Error on subscription GraphQL Server
I'm fairly new to GraphQl and I followed the GraphQL NodeJS backend tutorial here: GraphQL Realtime Subscriptions .我对 GraphQl 还很陌生,我在这里学习了 GraphQL NodeJS 后端教程: GraphQL 实时订阅。 Everything worked well and I completed the tutorial.
一切正常,我完成了教程。 Next I followed the VueJS with Apollo frontend tutorial here: Vue & Apollo Subscriptions .
接下来,我在此处遵循 VueJS 和 Apollo 前端教程: Vue & Apollo Subscriptions 。 I chose to use my own created GraphQL server from the first tutorial instead of using GraphCool, which is used in the frontend tutorial.
我在第一个教程中选择使用我自己创建的 GraphQL 服务器,而不是使用前端教程中使用的 GraphCool。 This is the part where I'm stuck.
这是我被卡住的部分。 If I call
如果我打电话
subscription {
Link(filter: {
mutation_in: [CREATED]
}) {
node {
id
url
description
}
}
}
in the GraphiQL client I do get the id
, url
and description
when I create a new link in a different browser tab with the data data: Link: node: {id: "59ef0bbeef32bb05692ee4b4", url: "http://new-test-url2.com", description: "Test description2"}
(This subscription call is also made in the backend tutorial).在 GraphiQL 客户端中,当我在不同的浏览器选项卡中使用数据
data: Link: node: {id: "59ef0bbeef32bb05692ee4b4", url: "http://new-test-url2.com", description: "Test description2"}
创建新链接时,我确实得到了id
、 url
和description
data: Link: node: {id: "59ef0bbeef32bb05692ee4b4", url: "http://new-test-url2.com", description: "Test description2"}
(这个订阅调用也是在后台教程中进行的)。 But when I call但是当我打电话
subscription {
Link(filter: {
mutation_in: [CREATED]
}) {
node {
id
url
description
postedBy {
id
name
}
votes {
id
user {
id
}
}
}
}
}
I get the error:我收到错误:
{message: "Cannot destructure property `Users` of 'undefined' or 'null'.",…}
{message: "Cannot destructure property `Votes` of 'undefined' or 'null'.",…}
with the data data:{Link: {node: null}}
与数据
data:{Link: {node: null}}
I just can't find the answer to this problem.我只是找不到这个问题的答案。 Hopefully someone can help me this this.
希望有人能帮我这个。 This is my code:
这是我的代码:
schema/index.js架构/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
}
schema/resolvers.js:架构/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();
},
},
Hoping you were able to solve this one since it has been so long, I just figured out this one today myself.这么久了,希望你能解决这个问题,我今天才自己解决了这个问题。 The issue here is that the subscription server was never passed in the context, ie the dataloaders/user information.
这里的问题是订阅服务器从未在上下文中传递,即数据加载器/用户信息。
In this lesson( https://www.howtographql.com/graphql-js/4-connectors/ ) you setup the context for the express server, but this was never added to the subscription server:在本课( 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,
}
In order to add this to the subscription server I used these options myself:为了将其添加到订阅服务器,我自己使用了以下选项:
const subscriptionBuildOptions = async (connectionParams,webSocket) =>
{
return {
dataloaders: buildDataloaders(mongo),
mongo,
}
}
I then added this to the SubscriptionServer by simply adding the onConnect Parameter:然后我通过简单地添加 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}.`)
});
And that should mostly get everything working.这应该主要使一切正常。 I personally am doing the reactjs tutorial, so not sure what individual issues there will be for that, but the reactjs tutorial api calls were a bit out of sync throughout.
我个人正在做 reactjs 教程,所以不确定会有什么个别问题,但是 reactjs 教程 api 调用在整个过程中有点不同步。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.