Циклические зависимости не могут быть разделены на соответствующие файлы

#javascript #node.js #graphql

Вопрос:

Есть два объекта, Пользователи и Компания, каждый пользователь работает в Компании, поэтому у него есть идентификатор компании, на который ссылаются через GraphQL. Аналогично, у каждой компании есть список пользователей, работающих на них.

Вот код:

company.js

 const UserType = require('./user')

const CompanyType = new GraphQLObjectType({
  name: 'Company',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    users: {
      type: new GraphQLList(UserType),        --------> Error:Expected {} to be a GraphQL type.
                                                        Expected UserType to be a GraphQL type.
      async resolve(parentValue, args) {
        return await axios(
          `http://localhost:3001/company/${parentValue.id}/users`
        ).then(({ data }) => data)
      },
    },
  }),
})
 

user.js

 const CompanyType = require('./company')

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    id: { type: GraphQLString },
    age: { type: GraphQLInt },
    name: { type: GraphQLString },
    company: {
      type: CompanyType,
      async resolve(parentValue, args) {
        console.log(parentValue)
        return await axios(
          `http://www.localhost:3001/company/${parentValue.companyId}`
        ).then((response) => response.data)
      },
    },
  }),
})
 

rootquery.js

 const UserType = require('./user')
const CompanyType = require('./company')

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryObjectType',
  fields: {
    user: {
      type: UserType,
      args: {
        id: { type: GraphQLString },
      },
      resolve: async (parentValue, args) => {
        return await axios(`http://localhost:3001/users/${args.id}`).then(
          ({ data }) => data
        )
      },
    },
    company: {
      type: CompanyType,
      args: {
        id: { type: GraphQLString },
      },
      resolve: async (parentValue, args) => {
        return await axios(`http://localhost:3001/company/${args.id}`).then(
          ({ data }) => data
        )
      },
    },
  },
})
 

Ошибка понятна из-за циклических зависимостей.
На случай, если я введу код user.js и company.js в rootquery.js, здесь нет никакой ошибки.
Есть ли способ отделить эти файлы, не сталкиваясь с ошибкой пустого объекта?

Комментарии:

1. заводские функции. например gist.github.com/fbaiodias/77406c29ddf37fe46c3c

2. Они уже используются в user.js и company.js, когда я предоставляю заводские функции в rootquery.js, предыдущая ошибка устранена, и вот новая ошибка : Ошибка: В одном из предоставленных типов для построения схемы отсутствует имя.

3. Куда вы экспортируете эти типы?

4. user.js и company.js экспортируются из их собственных соответствующих файлов

Ответ №1:

После небольшого исследования выяснилось, что везде, где вам нужно будет использовать циклическую зависимость, вы должны требовать ее в этот момент в своем коде, вместо того, чтобы требовать ее в качестве переменной. Например.

Ранее:

 const UserType = require('./user')        ---> This was null/empty as it wasn't yet 
                                               created

const CompanyType = new GraphQLObjectType({
  name: 'Company',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    users: {
      type: new GraphQLList(UserType),        --------> Error:Expected {} to be a 
                                                              GraphQL type.
                                                        Expected UserType to be a 
                                                              GraphQL type.
      async resolve(parentValue, args) {
        return await axios(
          `http://localhost:3001/company/${parentValue.id}/users`
        ).then(({ data }) => data)
      },
    },
  }),
})
 

Чтобы преодолеть эту проблему, мне потребовался необходимый модуль именно там, где он требуется

Решение:

 const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    name: { type: GraphQLString },
    id: { type: GraphQLString },
    age: { type: GraphQLInt },
    company: {
      **type: require('./company'),**            -----> This is where a dynamic 
                                                                 import                                                               
                                                             is being made
      async resolve(parentValue, args) {
        return await axios(
          `http://localhost:3001/users/${parentValue.id}`
        ).then(({ data }) => data)
      },
    },
  }),
})