GraphQL:提供的用于构建架构的类型之一缺少名称

时间:2020-04-16 20:48:37

标签: javascript node.js graphql node-modules

我正在学习GraphQL,所以遇到了一个奇怪的问题

我在一个文件Schema.js上有以下代码:

const graphQL = require('graphql');
const lodash = require('lodash')
const { GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLID, GraphQLSchema, GraphQLList } = graphQL;

const StatusType = new GraphQLObjectType({
name: 'Status',
fields: () => ({
    id: { type: GraphQLInt },
    statusName: { type: GraphQLString },
    user: {
        type: new GraphQLList(UserType),
        resolve(parentValue, args){
            
        }
    }
})
});

const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
    id: { type: GraphQLString },
    username: { type: GraphQLString },
    mail: { type: GraphQLString },
    password: { type: GraphQLString },
    status: { 
        type: StatusType,
        resolve(parentValue, args){
            
        }
    },
})
});

const RouteQuery = new GraphQLObjectType({
name: 'RouteQuery',
user: {
        type: UserType,
        args: { id: { type: GraphQLString } },
        resolve(parentValue, args){
            //return lodash.find(users, { id: args.id })
        }
    },
userSome: {
        type: new GraphQLList(UserType),
        args: { id: { type: GraphQLString } },
        resolve(parentValue, args){
            if (args.id) {
                //return users.filter(user => user.id === args.id);
            }
            //return users;
        }
    },
userAll: {
        type: new GraphQLList(UserType),
        resolve(parentValue){
            //return users
        }
    },
status:{
        type: StatusType,
        args: { id: { type: GraphQLInt } },
        resolve(parentValue, args){
            //return lodash.find(status, { id: args.id })
        }
    },
statusAll: {
        type: new GraphQLList(StatusType),
        resolve(parentValue){
            //return users
        }
    }
    }
});

module.exports = new GraphQLSchema({
query: RouteQuery
})

此代码成功运行,但是当我尝试将它们分成多个文件时:const StatusType & UserType类似以下情况: StatusType位于StatusType.js文件上,而UserType位于UserType.js文件上

StatuType.js文件:

const graphQL = require('graphql');
const { GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLID, GraphQLSchema, GraphQLList } = graphQL;
const UserType = require('./UserType')
const StatusType = new GraphQLObjectType({
name: 'Status',
fields: () => ({
    id: { type: GraphQLInt },
    statusName: { type: GraphQLString },
    user: {
        type: new GraphQLList(UserType),
        resolve(parentValue, args){
            //return users.filter(user => user.status === parentValue.id);
        }
    }
})
});
module.exports = StatusType;

UserType.js文件:

const graphQL = require('graphql');
const { GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLID, GraphQLSchema, GraphQLList } = graphQL;
const StatusType = require('./StatusType')

const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
    id: { type: GraphQLString },
    username: { type: GraphQLString },
    mail: { type: GraphQLString },
    password: { type: GraphQLString },
    status: { 
        type: StatusType,
        resolve(parentValue, args){
            //return lodash.find(status, { id: parentValue.status })
        }
    },
})
});
module.exports = UserType;

在Schema.js文件中,我包括了以下两个内容:

const StatusType = require('./StatusType');
const UserType = require('./UserType');

因此,我没有将所有代码都放在同一文件中,而是将StatusType和UserType放在了相应文件中。

但是当我运行此代码时,出现此错误:

enter image description here

所以我不知道这里出了什么问题:/

但是,当我尝试进入console.log时,我得到了const UserType = require('./UserType')作为响应:{就像在Schema.js上的同一代码上一样

3 个答案:

答案 0 :(得分:3)

您在nodeJ处理require的方式上遇到了问题。有关如何在节点中处理require的信息,请参见http://nodejs.org/api/modules.html#modules_cycles

具体针对您的情况,当您这样做:

const StatusType = require('./StatusType');
const UserType = require('./UserType');
  1. StatusType是从const StatusType = require('./StatusType');加载的
  2. StatusType.js UserType加载const UserType = require('./UserType')
  3. UserType.js 应该要求StatusType,但是nodeJ阻止了这一点以避免无限循环。结果,它执行下一行
  4. UserType初始化为new GraphQLObjectType(...),并将fields定义为函数。函数闭包将变量StatusType传递给尚未初始化的变量。这只是一个空的导出模块{}

您可以验证在创建console.log(StatusType);字段时添加UserType

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => {
    console.log(StatusType);
    return ({
      id: { type: GraphQLString },
      username: { type: GraphQLString },
      mail: { type: GraphQLString },
      password: { type: GraphQLString },
      status: {
        type: StatusType,
        resolve(parentValue, args) {

        }
      },
    });
  }
});

您将获得:

{} //instead of StatusType

当所有内容都在同一个文件中时,您没有遇到此问题,因为UserTypeStatusType都定义在同一个闭包中,而现在都定义在同一个闭包中。

要解决这个问题,您必须在同一级别上定义UserTypeStatusType并注入它们。 here是一个很好的例子。就您而言:

// StatusType.js
const StatusType = (types) => new GraphQLObjectType({
  name: 'Status',
  fields: () => {
    console.log(types.UserType);
    return ({
      id: { type: GraphQLInt },
      statusName: { type: GraphQLString },
      user: {
        type: new GraphQLList(types.UserType),
        resolve(parentValue, args) {

        }
      }
    });
  }
});

module.exports = StatusType;

// UserType.js
const UserType = (types) => new GraphQLObjectType({
  name: 'User',
  fields: () => {
    console.log(types.StatusType);
    return ({
      id: { type: GraphQLString },
      username: { type: GraphQLString },
      mail: { type: GraphQLString },
      password: { type: GraphQLString },
      status: {
        type: types.StatusType,
        resolve(parentValue, args) {

        }
      },
    });
  }
});
module.exports = UserType;

// Schema.js
const StatusTypeInject = require('./StatusType');
const UserTypeInject = require('./UserType');

const types = {};
types.StatusType = StatusTypeInject(types);
types.UserType = UserTypeInject(types);

const StatusType = types.StatusType;
const UserType = types.UserType;

答案 1 :(得分:0)

您可以在这里进行一些清理,这是我解决这些情况的方法:

[..]
// import GraphQLNonNull from the graphql lib
// In your case, I'd use GraphQLID instead of GraphQLString

userSome: {
  type: new GraphQLList(require('../path/to/UserType')),
  args: { id: { type: new GraphQLNonNull(GraphQLID) } },
  resolve: async (parentValue, args) => {
    // No need for the if statement as we'd sure to have an id.
    // return await filter users by id.
  }
},
[..]

和往常一样,将fields用作函数:fields: () => ({})

答案 2 :(得分:-1)

您要在声明之前在StatusType中导入UserType。

const StatusType = require('./StatusType');
const UserType = require('./UserType');