GraphQL循环依赖

时间:2017-03-01 12:08:12

标签: javascript node.js graphql circular-dependency

我对javascript很新,目前正在学习使用Node.js实现带有MongoDB后端的graphQL API。我遇到了两种类型之间循环依赖的问题。

基本上,我有一个经典的博客帖子/博客作者情况。帖子只有一个作者,因此猫鼬模式包含对该作者的引用。

在我的graphQL类型"作者"我想添加一个字段" posts"这使我可以从作者导航到他们写的所有帖子。引用不是在数据库模型中编码,而是通过控制器检索。这是我的博文代码。

var graphql = require("graphql");
var AuthorResolvers = require("../resolvers/author");
var PostResolvers = require("../resolvers/post");
var AuthorType = require("./author").AuthorType;

var PostType = new graphql.GraphQLObjectType({
  name: "PostType",
  fields: {
        _id: {
            type: graphql.GraphQLID
        },
        title: {
            type: graphql.GraphQLString
        },
        author: {
            type: AuthorType,
            description: "Author of this post",
            resolve: (post) => AuthorResolvers.retwArgs(post)
        }
    }
});

module.exports = {PostType};

resolvers.js文件只导出函数来寻址控制器。

我的作者类型定义如下:

var graphql = require ("graphql");
var AuthorResolvers = require("../resolvers/author");
var PostResolvers = require("../resolvers/post");

var AuthorType = new graphql.GraphQLObjectType({
  name: "AuthorType",
  fields: () => {
        var PostType = require("./post");
        return {
            _id: {
                type: graphql.GraphQLID
            },
            name: {
                type: graphql.GraphQLString
            },
            posts: {
                type: new graphql.GraphQLList(PostType),
                description: "Posts written by this author",
                resolve: (author) => PostResolvers.retwArgs(author)
            }
        }
    }
});

我已经尝试了两件事:

  1. 我使用了一个函数来返回fields字段。我认为这被称为thunk或封闭。
  2. 我需要在返回字段的函数中使用PostType。当我需要文件./post和其他要求时,错误已经被抛到文件的顶部。
  3. 当我尝试运行此服务器示例时,我收到错误:

    Can only create List of a GraphQLType but got: [object Object].
    

    指向

    type: new graphql.GraphQLList(PostType)
    

    作者。

    包含上面发布的类型定义的文件也会导出如下查询:

    var PostQuery = {
        posts: {
            type: new graphql.GraphQLList(PostType),
            description: "Posts of this Blog",
            resolve: PostResolvers.ret
        }
    };
    

    帖子就像这样

    var AuthorQuery = {
        authors: {
            type: new graphql.GraphQLList(AuthorType),
            description: "The authors working on this Blog",
            resolve: AuthorResolvers.ret
        }
    };
    

    分别为作者。所有内容都汇集在一个Schema文件中,如下所示:

    var graphql = require("graphql");
    var Author = require("./types/author").AuthorQuery;
    var Post = require("./types/post").PostQuery;
    
    var root_query = new graphql.GraphQLObjectType({  
      name: "root_query",
      fields: {
        posts: Post.posts,
        authors: Author.authors
      }
    });
    
    module.exports = new graphql.GraphQLSchema({
      query: root_query
    });
    

    最后是服务器:

    var graphql = require ('graphql').graphql  
    var express = require('express')  
    var graphQLHTTP = require('express-graphql')
    var Schema = require('./api/schema')
    
    var app = express()
      .use("/", graphQLHTTP(
        {
          schema: Schema,
          pretty: true,
          graphiql: true,
        }
      ))
      .listen(4000, function(err) {
        console.log('Running a GraphQL API server at localhost:4000');
      })
    

    我真的没有办法解决这种循环依赖。如果我只是在AuthorType定义中注释掉PostType的引用,那么服务器启动没有问题。非常感谢任何帮助。

    也许是为了更好地理解。目录结构如下所示:

    │   package.json
    │   server.js
    │
    ├───api
    │   │   schema.js
    │   │
    │   ├───controllers
    │   │       author.js
    │   │       post.js
    │   │
    │   ├───models
    │   │       author.js
    │   │       post.js
    │   │
    │   ├───resolvers
    │   │       author.js
    │   │       post.js
    │   │
    │   └───types
    │           author.js
    │           post.js
    │
    └───config
            db.js
    

2 个答案:

答案 0 :(得分:5)

这是模块循环依赖的典型问题 - 您可以参考这个问题How to deal with cyclic dependencies in Node.js。在这种情况下,它与GraphQL无关。

此外,您module.exports = { PostType } AuthorType var PostType = require('./post')执行var PostType = require('./post').PostTypeCan only create List of a GraphQLType but got: [object Object].不应该是PostType?我想这是你得到以下错误的原因:

{ PostType: ... }

因为您的GraphQLObjectType现在是/* ----- JavaScript ----- */ var menuButton = document.getElementById("menu-btn"); var dropBox = document.getElementById('drop-box'); var menuItem = document.getElementsByClassName('sub-menu-item'); dropBox.style.display = 'none'; menuButton.onclick = function() { if (dropBox.style.display == 'none') { dropBox.style.display = 'block'; } else { dropBox.style.display = 'none'; } };而不是/* ----- CSS ----- */ #menu-btn { margin: 20px auto; width: 200px; height: 50px; background-color: green; text-align: center; padding-top: 30px; cursor: pointer; } #drop-box { width: 191px; position: absolute; left: 697px; top: 100px; margin: 0; padding: 0; } #drop-box li { list-style: none; } .linkBtn { width: 100%; background-color: orange; display: block; margin: 3px; padding: 5px; color: black; text-align: center; } .linkBtn:hover { background-color: green; }实例。

答案 1 :(得分:4)

piotrbienias的反应让我找到了正确的线索。我之前读过它但完全不明白。在需要类之前,必须定义导出。在我的情况下,我能够像这样解决它:

module.exports.AuthorType = new graphql.GraphQLObjectType({
  name: "AuthorType",
  fields: () => {
        var PostType = require("./post").PostType;
        return {
            _id: {
                type: graphql.GraphQLID
            },
            name: {
                type: graphql.GraphQLString
            },
            posts: {
                type: new graphql.GraphQLList(PostType),
                description: "Posts written by this author",
                resolve: (author) => PostResolvers.retwArgs(author)
            }
        }
    }
});

,类似于PostType。这样,导出就会在调用require之前定义。

非常感谢!