graphql - 将 GraphQL 类型模块化到单独的文件中

标签 graphql

我有一个 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.jstypes/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/

相关文章:

javascript - react : How to refresh the data in the table after button click

node.js - 使用 GraphQL 和 NodeJS 插入后的 PostgreSQL "syntax error at end of input"

javascript - react 结合不同的包装器

azure - Azure APIM 是否支持 GraphQL?

typescript - 如何在 type-graphql 中触发订阅?

reactjs - 如何从 React 中的 Apollo 订阅组件刷新查询/缓存

javascript - 如何进行 ShopifyQL 查询?

javascript - 在react-apollo中使用refetchQueries时使用现有变量

rust - 是否可以使用 Tokio 和 Juniper 在 GraphQL 对象字段中执行任何类型的并行计算?

encoding - 如何在 GraphQL 服务器上启用 gzip?