GraphQL循环依赖

Bas*_*ian 5 javascript circular-dependency node.js graphql

我是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};
Run Code Online (Sandbox Code Playgroud)

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)
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

我已经尝试了两件事:

  1. 我使用函数返回fields字段.我认为这被称为thunk或闭包.
  2. 我需要在返回字段的函数中使用PostType.当我需要文件./post和其他要求时,错误已经被抛到文件的顶部.

当我尝试运行此服务器示例时,我收到错误:

Can only create List of a GraphQLType but got: [object Object].
Run Code Online (Sandbox Code Playgroud)

哪个指向该线

type: new graphql.GraphQLList(PostType)
Run Code Online (Sandbox Code Playgroud)

在作者.

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

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

对于这个帖子,像这样

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

分别为作者.所有内容都集中在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
});
Run Code Online (Sandbox Code Playgroud)

最后是服务器:

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');
  })
Run Code Online (Sandbox Code Playgroud)

我真的没有办法解决这个循环依赖.如果我只是在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
Run Code Online (Sandbox Code Playgroud)

pio*_*ias 6

这是模块循环依赖的典型问题 - 你可以参考这个问题如何处理Node.js中的循环依赖.在这种情况下,它与GraphQL无关.

更重要的是,你module.exports = { PostType }AuthorType演出时会这样做var PostType = require('./post'),不应该这样var PostType = require('./post').PostType吗?我想这是你得到以下错误的原因:

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

因为你PostType现在{ PostType: ... }而不是一个GraphQLObjectType实例.


Bas*_*ian 5

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)
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

和类似的PostType。这样,将在调用require之前定义导出。

非常感谢!

  • 这是我的解决方案-关键是对`fields`参数使用回调函数,并将您的require()放入该函数中 (2认同)
  • 这是一种称为“ thunk”的模式。 (2认同)