我正在学习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放在了相应文件中。
但是当我运行此代码时,出现此错误:
所以我不知道这里出了什么问题:/
但是,当我尝试进入console.log时,我得到了const UserType = require('./UserType')
作为响应:{就像在Schema.js上的同一代码上一样
答案 0 :(得分:3)
您在nodeJ处理require
的方式上遇到了问题。有关如何在节点中处理require
的信息,请参见http://nodejs.org/api/modules.html#modules_cycles。
具体针对您的情况,当您这样做:
const StatusType = require('./StatusType');
const UserType = require('./UserType');
StatusType
是从const StatusType = require('./StatusType');
加载的UserType
加载const UserType = require('./UserType')
StatusType
,但是nodeJ阻止了这一点以避免无限循环。结果,它执行下一行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
当所有内容都在同一个文件中时,您没有遇到此问题,因为UserType
和StatusType
都定义在同一个闭包中,而现在都定义在同一个闭包中。
要解决这个问题,您必须在同一级别上定义UserType
和StatusType
并注入它们。 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');