简体   繁体   English

订阅 GraphQL 服务器时出错

[英]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"}创建新链接时,我确实得到了idurldescription 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.

相关问题 带有多线程NodeJS服务器的Graphql订阅 - Graphql subscription with multithreaded nodeJS server Apollo graphQL 服务器订阅初始响应 - Apollo graphQL Server subscription initial response 订阅 URL 在 Apollo Graphql 订阅服务器中不起作用 - Subscription URL doesn't work in Apollo Graphql Subscription Server GraphQl 订阅错误:无法连接到 websocket 端点 ws://localhost:5000/graphql - GraphQl Subscription error: Could not connect to websocket endpoint ws://localhost:5000/graphql 如何在Graphql.js中使用GraphQL的订阅 - How to use subscription of GraphQL in Graphql.js graphql apollo-server 中的文件上传错误 - File upload error in graphql apollo-server 使用 GraphQL 设置订阅的问题 - Issue setting up subscription with GraphQL GraphQL / Apollo服务器指令导致架构错误 - GraphQL / Apollo Server Directives leading to schema error 为什么在运行带有 Redis 的 GraphQL 订阅时,它会抛出错误 cannot read property of undefined (reading 'length')? - Why does it throw an error cannot read property of undefined (reading 'length') when running a GraphQL Subscription with Redis? Create subscription with Stripe in Lambda function 失败并出现内部服务器错误 - Create subscription with Stripe in Lambda function fails with internal server error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM