【发布时间】:2020-06-01 23:00:03
【问题描述】:
过去一天左右我一直遇到这个 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 未通过 (undefined),它只会返回系统中的所有问题。这意味着在问卷类型中,在 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 解析器增加了更多复杂性。
感谢任何帮助和见解。
【问题讨论】:
标签: javascript graphql apollo-server