我有一个 GraphQL 实现,其中包含一个整体 types/index.js 文件,该文件当前包含两个类型定义:
const graphql = require('graphql');
const Book = require('../../../models/book');
const Author = require('../../../models/author');
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
} = graphql;
const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author: {
type: AuthorType,
resolve: (parent, args) => {
// code to get data from db
return Author.findById(parent.authorId);
},
},
}),
});
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: new GraphQLList(BookType),
resolve: (parent, args) => {
// code to get data from db
return Book.find({authorId: parent.id});
},
},
}),
});
module.exports = {BookType, AuthorType};
这是我导入到 schema.js 文件中的文件,供根查询和突变使用:
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
} = require('graphql');
const Book = require('../../../models/book');
const Author = require('../../../models/author');
const {BookType, AuthorType} = require('../types');
// QUERIES
//------------------------------------------------------------------------------------------------------
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve: (parent, args) => {
// code to get data from db
return Book.findById(args.id);
},
},
author: {
type: AuthorType,
args: { id: { type: GraphQLID } },
resolve: (parent, args) => {
// code to get data from db
return Author.findById(args.id);
},
},
books: {
type: new GraphQLList(BookType),
resolve: (parent, args) => {
// code to get data from db
return Book.find({});
},
},
authors: {
type: new GraphQLList(AuthorType),
resolve: (parent, args) => {
// code to get data from db
return Author.find({});
}
},
},
});
// MUTATIONS
//------------------------------------------------------------------------------------------------------
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addAuthor: {
type: AuthorType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
age: { type: new GraphQLNonNull(GraphQLInt) }
},
resolve(parent, args) {
let author = new Author({
name: args.name,
age: args.age
});
return author.save();
}
},
addBook: {
type: BookType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
genre: { type: new GraphQLNonNull(GraphQLString) },
authorId: { type: new GraphQLNonNull(GraphQLID) },
},
resolve(parent, args) {
let book = new Book({
name: args.name,
genre: args.genre,
authorId: args.authorId,
});
return book.save();
},
},
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation,
});
但随着项目的发展,我预计会有数十种具有大量双向关系的类型。因此,我想将所有类型模块化为单独的文件,例如 types/BookType.js、types/AuthorType.js 等,而不是单个 >types/index.js 就像我现在一样。鉴于双向关系,实现此目的的最佳方法是什么?
最佳答案
将类型分离到单独的文件中时,您需要处理双向关系。在这种情况下,AuthorType 需要 BookType,反之亦然。因此,您需要在 types/BookTypes.js 中导入 AuthorType,在 types/AuthorType.js 中导入 BookType,但这将引入经典的循环依赖问题(在 AuthorType 导出之前,它需要 BookType,反之亦然)这在节点项目中很常见。您可以阅读更多相关信息here 。要解决此问题,请将您的 require 调用转移到两种类型的文件末尾。所以你的代码看起来有点像这样:
types/BookType.js
const graphql = require('graphql');
const Book = require('../../../models/book');
const Author = require('../../../models/author');
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
} = graphql;
const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author: {
type: AuthorType,
resolve: (parent, args) => {
// code to get data from db
return Author.findById(parent.authorId);
},
},
}),
});
module.exports = BookType;
// This is here to prevent circular dependencies problem which will lead to the formation of infinite loop
const AuthorType = require("./AuthorType");
types/AuthorType.js
const graphql = require('graphql');
const Book = require('../../../models/book');
const Author = require('../../../models/author');
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
} = graphql;
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: {
type: GraphQLID
},
name: {
type: GraphQLString
},
age: {
type: GraphQLInt
},
books: {
type: new GraphQLList(BookType),
resolve: (parent, args) => {
// code to get data from db
return Book.find({
authorId: parent.id
});
},
},
}),
});
module.exports = AuthorType;
// This is here to prevent circular dependencies problem which will lead to the formation of infinite loop
const BookType = require("./BookType");
此外,最好有一个 types/index.js 来充当导入/导出的处理程序。您可以将每种类型导出到index.js,并从任何地方获取您想要的任何内容。这可以让您避免编写大量困惑的代码,因为现在您可以执行以下操作:
const { BookType, AuthorType, OtherType } = require("../types/index");
关于graphql - 将 GraphQL 类型模块化到单独的文件中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52327007/