在过去一天左右的时间里,我一直遇到这个 GraphQL 错误,而且我很难确定问题出在哪里。我希望以下内容有意义......
在我的项目中,我有以下 GraphQL 类型;调查问卷和问题是一个调查问卷有很多问题,一个问题属于一个调查问卷。
我有以下查询:getQuestionnaires
(获取所有调查问卷)、getQuestionnaire
(通过 ID 获取单个调查问卷)、getQuestions
(获取所有问题,可以是系统中的所有问题,也可以是通过指定 questionnaireId
获取调查问卷的问题。
这是问卷类型(为了简洁起见,我省略了一些属性):
import {
GraphQLID,
GraphQLObjectType,
GraphQLNonNull,
} from 'graphql'
import QuestionType from './Question'
import QuestionResolver from '../resolver/question'
const QuestionnaireType: GraphQLObjectType = new GraphQLObjectType({
name: 'Questionnaire',
fields() {
return {
id: {
type: new GraphQLNonNull(GraphQLID),
},
// other literal attributes go here
questions: QuestionResolver.query.getQuestions,
}
},
})
export default QuestionnaireType
如您所见,问卷类型的 questions
属性只是调用 getQuestions
的解析器。
这是 getQuestions
的解析器:
import {
GraphQLList,
GraphQLID
} from 'graphql'
import QuestionType from '../../type/Question'
export default {
type: GraphQLList(QuestionType),
description: 'Returns a list of questions',
args: {
questionnaireId: {
type: GraphQLID,
description: 'Questions that belong to this questionnaire',
},
},
async resolve(source: any, { questionnaireId = undefined }: any, ctx: any): Promise<any> {
// Based on the `questionnaireId` get the questions. If `undefined` get "all" questions.
},
}
如您所见,getQuestions
返回一个 GraphQLList(QuestionType)
。这给我们带来了问题类型:
import {
GraphQLID,
GraphQLObjectType,
GraphQLNonNull,
} from 'graphql'
import QuestionnaireType from './Questionnaire'
import QuestionnaireResolver from '../resolver/questionnaire'
const QuestionType: GraphQLObjectType = new GraphQLObjectType({
name: 'Question',
fields() {
return {
id: {
type: new GraphQLNonNull(GraphQLID),
},
questionnaire: QuestionnaireResolver.query.getQuestionnaire,
}
},
})
export default QuestionType
好的。到目前为止,一切都很好。此代码编译并运行。
但是,这段代码有一个问题。 getQuestions
解析器将调查问卷 ID 作为参数 (questionnaireId
)。如果未传递调查问卷 ID(未定义
),它只会返回系统中的所有问题。这意味着在问卷类型中,在 questions
属性上,我们不想直接调用 getQuestions
解析器,但我们希望将其包装在一个解析器中,以提取source.id
(source
是本上下文中的调查问卷)并将其作为参数传递给 getQuestions
解析器。如果我们不这样做,那么在调查问卷上查询问题将始终返回系统中的所有问题,这是我们不想要的。
因此,我们将解析器包装在一个解析器中,该解析器在调用 getQuestions
解析器之前提取问卷 ID。我们的调查问卷类型现在如下所示:
import {
GraphQLID,
GraphQLObjectType,
GraphQLNonNull,
} from 'graphql'
import QuestionType from './Question'
import QuestionResolver from '../resolver/question'
const QuestionnaireType: GraphQLObjectType = new GraphQLObjectType({
name: 'Questionnaire',
fields() {
return {
id: {
type: new GraphQLNonNull(GraphQLID),
},
// other literal attributes go here
questions: {
type: GraphQLList(QuestionType),
async resolve(source: any, args: any, ctx: any): Promise<any> {
return QuestionResolver.query.getQuestions.resolve(
source,
{
questionnaireId: source.questionnaireId,
},
ctx
)
},
},
}
},
})
export default QuestionnaireType
我们现在已经封装了 getQuestions
解析器来提取 source.id
(即问卷 ID),以便我们始终可以将其传递给 getQuestions
解析器(因为这是我们在这种情况下总是想要的)。
但是,当我执行上述操作时。我收到此错误:
[Node] /Project/api/node_modules/graphql/type/definition.js:91
[Node] throw new Error("Expected ".concat((0, _inspect.default)(type), " to be a GraphQL type."));
[Node] ^
[Node]
[Node] Error: Expected undefined to be a GraphQL type.
[Node] at assertType (/Project/api/node_modules/graphql/type/definition.js:91:11)
[Node] at new GraphQLList (/Project/api/node_modules/graphql/type/definition.js:307:19)
[Node] at Object.GraphQLList (/Project/api/node_modules/graphql/type/definition.js:309:12)
[Node] at Object.<anonymous> (/Project/api/build/graphql/resolver/question/getQuestions.js:11:21)
[Node] at Module._compile (internal/modules/cjs/loader.js:936:30)
[Node] at Object.Module._extensions..js (internal/modules/cjs/loader.js:947:10)
[Node] at Module.load (internal/modules/cjs/loader.js:790:32)
[Node] at Function.Module._load (internal/modules/cjs/loader.js:703:12)
[Node] at Module.require (internal/modules/cjs/loader.js:830:19)
[Node] at require (internal/modules/cjs/helpers.js:68:18)
我被难住了......
getQuestions
第 11 行是:
08: export default {
09: type: GraphQLList(QuestionType),
10: description: 'Returns a list of questions',
11: args: {
12: questionnaireId: {
13: type: GraphQLID,
14: description: 'Questions that belong to this questionnaire',
15: },
我想我已经尝试了所有能想到的方法来找到问题所在。我的项目很大,我在其他几个地方使用这种技术没有问题,但由于某种原因,在这个特定的场景中它无法编译..
我目前唯一的解决方法是在 getQuestions
解析器中使用类似的方法:
import {
GraphQLList,
GraphQLID
} from 'graphql'
import QuestionType from '../../type/Question'
export default {
type: GraphQLList(QuestionType),
description: 'Returns a list of questions',
args: {
questionnaireId: {
type: GraphQLID,
description: 'Questions that belong to this questionnaire',
},
},
async resolve(source: any, { questionnaireId = undefined }: any, ctx: any): Promise<any> {
// The workaround
const id = questionnaireId || source.id
},
}
但是,getQuestions
解析器没有责任查看source
来提取参数,而且 source
在技术上可以是问卷之外的另一个对象,为 getQuestions
解析器增加了更多复杂性。
感谢任何帮助和见解。
最佳答案
您需要查看编译后的代码来跟踪错误。不过,根据堆栈跟踪,QuestionType
的计算结果似乎是 undefined
。当您存在循环依赖关系时(即模块 A 导入模块 B,模块 B 导入模块 A 等),就会发生这种情况。
您通常应该避免在解析器内部调用其他解析器。如果有大量重复,可以将共享逻辑提取到一个可以从两个解析器调用的通用函数中。当我们的解析器包含业务逻辑时,很可能会发生这种情况 - 尝试使解析器尽可能精简,将业务逻辑隔离在单独的模型或服务中,然后可以从解析器调用其方法,这是一个很好的做法。
如果不查看所有相关代码,就很难知道如何修复循环依赖。解决任何循环依赖关系的有保证的方法是将 import 语句替换为 fields
函数内的动态 require
。但是,您可能不会发现该解决方案特别优雅。一个好的第一步可能是整合一些模块 - 例如,创建一个包含问题类型以及所有相关查询和突变字段的问题模块。
关于javascript - GraphQL错误: Expected undefined to be a GraphQL type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60272156/