如何在Apollo GraphQL中添加字段解析器?含传统写法对比
Apollo GraphQL 字段解析器的等效写法
既然你已经熟悉传统GraphQL.js的写法,那咱们直接对应到Apollo的常用实现方式——SDL(Schema Definition Language)配合独立的Resolvers对象,这也是Apollo推荐的更清晰的架构模式。
步骤1:用SDL定义你的类型
首先,先通过SDL来定义Lecture和Question类型,替代传统的GraphQLObjectType实例:
type Lecture { id: ID! questions: [Question!]! } type Question { # 这里根据你的QuestionType定义对应的字段,比如: id: ID! text: String! }
步骤2:编写对应的Resolvers对象
接下来,你需要创建一个resolvers对象,把字段的解析逻辑单独抽离出来,这就对应你原来代码里的resolve函数:
const resolvers = { Lecture: { // 这里的parent参数对应你原来的{ _id },也就是当前的Lecture对象 questions: async (parent, args, context) => { // context.models 对应你原来的{ models }上下文 return context.models.Lecture.findQuestions(parent.id); } } };
和传统写法的对应关系
对比你给出的传统代码,核心逻辑是完全一致的,只是组织方式不同:
- 原来的
GraphQLObjectType里的fields定义,拆分到了SDL的类型定义中 - 原来每个字段的
resolve函数,统一放到了resolvers对象下对应类型的属性里 - 参数映射:
parent(原代码的第一个参数{ _id })、args、context(原代码的第三个参数{ models })
整合到Apollo Server里
最后,把SDL和resolvers一起传入Apollo Server的配置:
import { ApolloServer } from '@apollo/server'; import { startStandaloneServer } from '@apollo/server/standalone'; // 你的SDL可以写成字符串,或者用gql标签包裹(推荐) const typeDefs = ` type Lecture { id: ID! questions: [Question!]! } type Question { id: ID! text: String! } # 别忘了定义查询入口,比如: type Query { getLecture(id: ID!): Lecture } `; const resolvers = { Lecture: { questions: async (parent, args, context) => { return context.models.Lecture.findQuestions(parent.id); } }, Query: { getLecture: async (parent, args, context) => { return context.models.Lecture.findById(args.id); } } }; // 启动服务器 const server = new ApolloServer({ typeDefs, resolvers }); const { url } = await startStandaloneServer(server, { context: async () => ({ models: { /* 你的模型实例 */ } }) });
额外说明:代码优先的方式(可选)
如果你更喜欢用代码优先的模式(比如结合TypeScript),Apollo生态也支持用装饰器来定义类型和解析器,比如使用type-graphql或者NestJS的GraphQL模块,但上面的SDL+resolvers是最基础、最通用的Apollo写法,和你原来的传统写法直接对应。
内容的提问来源于stack exchange,提问作者Coherent
相关产品推荐
相关产品推荐

