graphql - 将 GraphQL 类型模块化到单独的文件中
问题描述
我有一个带有单个整体types/index.js文件的 GraphQL 实现,该文件当前包含两个类型定义:
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,反之亦然),这在节点项目中很常见。你可以在这里阅读更多关于它的信息。要处理此问题,请在两种类型的文件末尾转移您的 require 调用。所以你的代码看起来有点像这样:
类型/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");
类型/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");
推荐阅读
- python - 使用 HTML 和 Flask 传递信息
- protocol-buffers - 确保 flink 中 protobuf 状态对象的状态模式演变
- java - 尝试配置 Javamail 以接收电子邮件时出错。错误:握手失败
- javascript - AngularJS 根据“projectName”选择超链接
- c# - 我们可以在 Excel 窗口中找到 activeCell 的确切位置吗?
- database-design - 在 OLAP 多维数据集中存储不同时间间隔的最佳实践
- java - Apache Poi 4.1.2 和 net.sf.jxls (jxls-core 1.0.6) 之间的兼容性
- python - Python,如何在 b[z] 中为 z 添加 +1?
- html - 如何创建与具有可滚动主体的容器高度相同的引导卡
- asp.net-core - Microsoft.AspNetCore.Server.HttpSys DLL 升级后的 400 错误请求