拓冰建站拓冰建站
首页 / 资讯中心 / 正文

HowToGraphQL 教程:用 Apollo Server 与 graphql-js 实现并解析第一个 GraphQL Query(feed 查询全流程)

【免费下载链接】howtographqlThe Fullstack Tutorial for GraphQL项目地址https://gitcode.com/gh_mirrors/ho/howtographql点击查看免费下载本篇指南是 HowToGraphQL 仓库中 graphql-js 后端教程 的第二章实战章节面向 Node.js 开发者讲解如何在一个基于apollo-server^2graphql-js的 GraphQL 服务器上通过**schema-firstSchema 驱动**的开发流程新增一个feed查询实现 Hacker News 克隆应用的核心功能——拉取用户发布的链接Link列表。读完本文你将掌握扩展 GraphQL Schema 定义、编写根字段与对象字段解析器resolver、在 GraphQL Playground 中验证查询以及理解 GraphQL 服务器“按查询形状逐级调用 resolver”的查询解析机制。在前一章 Getting Started 中你已经用npm install apollo-server^2 graphql^14.6.0初始化了一个名为hackernews-node的项目并在src/index.js中定义了一个只含info: String!根字段的极简 Schema成功发出了人生第一个 GraphQL 查询query { info }。现在是时候让这个 API 真正承担起业务职责了。为 API 添加第一个业务操作feed 查询本教程要构建的是一个 Hacker News 克隆应用其第一个 API 操作就是查询用户发布的链接links流feed。本节将完整走一遍“Schema 驱动开发”的标准流程。Schema-first 开发流程加功能的两个固定步骤每当你要为 GraphQL API 新增一个功能过程几乎都是固定不变的扩展 GraphQL Schema 定义——在typeDefs或独立的.graphql文件中添加新的根字段root field必要时同时新增对象类型object type为新增字段实现对应的解析器函数resolver functions。这套流程被称为schema-driven / schema-first developmentSchema 驱动开发。它强调“先定义契约再实现逻辑”Schema 是 API 的契约与文档resolver 是这个契约的具体执行者。这一点在你的示例项目hackernews-node中体现得淋漓尽致——src/index.js里typeDefs契约与resolvers实现始终成对出现。第一步扩展 Schema——定义 Link 类型与 feed 根字段打开src/index.js将typeDefs常量更新为如下内容const typeDefs type Query { info: String! feed: [Link!]! } type Link { id: ID! description: String! url: String! } 这段 Schema 做了两件事新增了一个Link对象类型表示可以被发布到 Hacker News 上的链接包含id、description、url三个字段在Query根类型上新增根字段feed返回[Link!]!——即一个Link 元素列表。注意[Link!]!中两个感叹号各自的含义这在 GraphQL 中称为类型修饰符type modifiers写法含义Link!元素非空列表中的每个元素都不能为null即不会出现空位[Link!]!列表非空整个列表本身不能为null最坏情况是空列表[]因此feed查询要么返回空列表要么返回一个全部由非空Link对象组成的列表绝不可能返回null。这个“永不 null”的强保证正是上一章中info: String!的感叹号语义在列表场景下的推广graphql-js参考实现会在运行时校验 resolver 的返回值是否符合 Schema 声明从根上帮你拦截掉“返回 null 给非空字段”这类低级错误。第二步实现 resolver——喂入内存数据接下来在index.js中添加一个存放模拟数据的links列表并更新resolvers// 1 let links [{ id: link-0, url: www.howtographql.com, description: Fullstack tutorial for GraphQL }] const resolvers { Query: { info: () This is the API of a Hackernews Clone, // 2 feed: () links, }, // 3 Link: { id: (parent) parent.id, description: (parent) parent.description, url: (parent) parent.url, } }逐条解读编号注释links变量用于在运行时保存链接数据。目前所有数据都只存在内存中尚未接入数据库——这意味着一旦服务器重启数据就会丢失。后续章节Adding a Database、Connecting Server and Database会引入 Prisma SQLite 来持久化数据。为feed根字段新增 resolver。resolver 的名字必须与 Schema 中的字段名完全一致——resolvers.Query.feed严格对应type Query { feed: ... }Apollo Server 正是靠这种命名约定把 Schema 字段与实现函数一一绑定。为Link类型的三个字段各加一个 resolver每个 resolver 接收parent参数并从中取出对应属性。parent的含义马上会专门讲解。补充说明resolvers对象的结构与typeDefs中的类型结构是同构的——Query.info、Query.feed、Link.id…… 这既是 Apollo 约定的查找规则也是你在编写 resolver 时最容易对照 Schema 检查的地方。在 GraphQL Playground 中测试 feed 查询重启服务器以加载新代码先按CTRLC停止正在运行的服务器如果还在运行的话再执行node src/index.js然后打开浏览器访问http://localhost:4000。你会进入 GraphQL Playground——这个内置于 Apollo Server 的“GraphQL IDE”会在右侧的DOCS面板中根据 Schema自动生成 API 文档。展开文档即可看到除了info之外feed查询已经可用。在左侧编辑区发送如下查询query { feed { id url description } }服务器返回的正是links数组中的数据{ data: { feed: [ { id: link-0, url: www.howtographql.com, description: Fullstack tutorial for GraphQL } ] } }建议动手实验从 selection set选择集中随意删掉某个字段比如只查feed { id }再观察服务器返回的形状变化。你会发现响应结构永远严格跟随查询结构——这正是 GraphQL“按需取数”的直观体验。深入原理GraphQL 查询解析Query Resolution过程现在来揭示一个关键机制GraphQL 服务器究竟是如何解析一条入站查询的查询由字段组成每个字段都有 resolver回顾上面的查询query { feed { id url description } }查询中出现了 4 个字段feed、id、url、description。它们全部可以在 Schema 定义中找到。而 Schema 中的每一个字段不只是根字段背后都有一个 resolver 函数负责返回该字段的数据。那么查询解析过程是什么其实非常简单GraphQL 服务器只需要为查询中出现的所有字段逐一调用对应的 resolver 函数然后按照查询自身的形状把返回值打包成响应即可。换句话说查询解析本质上就是一场“编排 resolver 调用”的交响乐。resolver 的四个参数与 parent父级结果参数你可能已经注意到上面Link的三个 resolver 看起来极其琐碎Link: { id: (parent) parent.id, description: (parent) parent.description, url: (parent) parent.url, }这里有两个重要事实需要澄清每个 GraphQL resolver 函数实际上接收 4 个入参本场景用不到另外三个所以被省略了。在后续章节中你会逐一认识它们其中第二个参数args用于携带操作参数——比如下一章 A Simple Mutation 中post(url: String!, description: String!): Link!里的url和description就是通过args传入 resolver 的。第一个参数通常命名为parent也有人叫root它是上一级 resolver 执行层的返回值。嵌套查询 多级 resolver 执行GraphQL 查询是可以嵌套的。每一层嵌套即每一组花括号{}对应一级 resolver 执行层。上面的feed查询因此有两级执行层第一级调用feedresolver返回links数组中的全部数据。第二级得益于 Schema 中feed: [Link!]!的声明服务器知道feed返回的是Link元素列表于是智能地为上一级返回列表中的每一个元素依次调用Link类型的 resolver。因此在三个Linkresolver 中收到的parent对象正是links列表中的那个元素。用一张层级关系图可以更直观地理解执行层级调用的 resolver传入的 parent返回值第 1 级Query.feed无根字段links数组第 2 级Link.id/Link.url/Link.descriptionlinks数组中的单个元素该元素的id/url/description琐碎的 resolver 可以省略因为Link的三个 resolver 实现过于琐碎实际上你可以直接删掉它们——Apollo Server / graphql-js 会自动推断这类“字段名与父对象属性同名”的默认解析行为服务器运行结果与保留它们时完全一致const resolvers { Query: { info: () This is the API of a Hackernews Clone, feed: () links, }, }这里写出来纯粹是为了让你看清引擎盖下面到底发生了什么。这一省略技巧在下一章 A Simple Mutation 中会被正式采用——那时resolvers中将只保留Query与Mutation两层。从源码看这套教程站点的渲染机制作为 HowToGraphQL 开源仓库本身你阅读的这份章节文档并不是孤立的 Markdown而是被站点构建管线深度定制过的“教程组件”。如果你对这套教程格式的底层实现感兴趣可以从以下源码路径继续深挖gatsby-node.js 为每一篇 Markdown 章节MarkdownRemark节点生成站点路由 slug例如本文对应的graphql-js分组章节会被映射为独立页面src/components/Tutorials/Markdown.tsx 负责把章节 HTML 渲染为教程页其中Instruction操作指示块、Pre带文件路径与复制按钮的代码块、Playground内嵌 GraphQL 演练场等特殊组件会被逐一解析src/components/Tutorials/Pre.tsx 解析代码块上的path注解把类似../hackernews-node/src/index.js的相对路径归一化后链接到示例仓库对应文件——这也是本教程中所有代码块都带“文件路径标注”的原因src/components/Tutorials/Chapter.tsx 负责章节页组装文章正文之外还会根据 frontmatter 中的question/answers/correctAnswer渲染章末测验并指向下一章。每章文档开头的 YAML frontmattertitle、description、question、answers、correctAnswer即按 meta/writing-guidelines.md 约定的写作规范编写question与answers构成了读者阅读完本章后需要回答的选择题。例如本章的测验问题是“GraphQL 查询是如何被解析的”正确答案正是本文核心结论通过调用查询中所包含字段对应的 resolver 函数。本章小结与下一步Schema-first 开发流程加功能 先扩 Schema根字段 对象类型再写 resolver非空与列表修饰符[Link!]!保证列表永不为null、元素永不为nullResolver 命名约定resolver 必须与 Schema 字段同名resolvers结构需与 Schema 结构同构查询解析机制服务器为查询中的每个字段调用其 resolver按查询形状组装响应嵌套查询逐级传递parent琐碎 resolver 可省略字段名与父对象属性一致的 resolver 会被自动推断。目前feed查询返回的数据仅存于内存数组links中服务器一重启数据就消失。下一步你将学习如何添加**变更Mutation**操作post让客户端能真正向服务器发布新链接——同时你会认识 resolver 的第二个参数args并尝试把 Schema 抽取到独立的schema.graphql文件中。继续阅读 A Simple Mutation。赞分享【免费下载链接】howtographqlThe Fullstack Tutorial for GraphQL项目地址https://gitcode.com/gh_mirrors/ho/howtographql点击查看免费下载相关推荐用 Nexus 实现 GraphQL 第一个查询TypeScript Apollo Server 中定义 Schema、编写 Resolver 与理解查询解析流程用 Nexus 实现 GraphQL 第一个查询TypeScript Apollo Server 中定义 Schema、编写 Resolver 与理解查询在 Node.js TypeScript GraphQL 服务器中实现第一个 feed 查询Schema、Resolver 与查询解析流程在 Node.js TypeScript GraphQL 服务器中实现第一个 feed 查询Schema、Resolver 与查询解析流程 本篇指南基于HowToGraphQL TypeScript 教程实战用 graphql-tools/schema 构建并本地执行第一个 GraphQL SchemaHowToGraphQL TypeScript 教程实战用 graphql tools/schema 构建并本地执行第一个 GraphQL Schema 本上一篇小说下载终极指南5分钟学会保存全网小说告别404错误下一篇CodeMirror 6移动端适配终极指南打造完美响应式代码编辑器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门