我对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)
}
}
}
});
我已经尝试了两件事:
当我尝试运行此服务器示例时,我收到错误:
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
答案 0 :(得分:5)
这是模块循环依赖的典型问题 - 您可以参考这个问题How to deal with cyclic dependencies in 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
现在是/* ----- 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之前定义。
非常感谢!