概述
在本课中,我们将
- 探索客户端请求数据以及GraphQL 服务器 如何检索数据。
- 了解组成GraphQL 服务器 的组件
- 了解GraphQL 模式 语法的基础知识: SDL 或 模式定义语言
GraphQL 操作的流程
我们的应用程序需要为特定页面获取数据。
为了获取这些数据,它会发送一个 GraphQL 操作 到我们的 GraphQL 服务器。应用程序将操作塑造成一个字符串,该字符串定义了其所需的 选择集 的 字段。然后,它以 HTTP POST
或 GET
请求的形式将该操作发送到服务器。
服务器端
当我们的服务器收到 HTTP 请求时,它首先会提取包含 GraphQL 操作 的字符串。它解析并将其转换为更容易操作的形式:一个称为 文档 的树状结构 AST(抽象语法树)。使用此 AST,服务器可以根据模式中的类型和 字段 验证 操作。
如果出现任何错误(例如,请求的 字段 未在模式中定义,或者 操作 格式错误),服务器会抛出错误并将其立即发送回应用程序。
在这种情况下, 操作 看起来没问题,服务器可以“执行”它。这意味着服务器可以继续其处理过程并实际获取数据。服务器会遍历 AST。
对于 操作 中的每个 字段,服务器都会调用该字段的 解析器 函数。解析器函数的任务是通过从正确的数据源(例如数据库或 REST API)获取正确的数据来“解析”其字段。这些 数据源 不一定需要在 GraphQL 服务器 内,它们可以是外部托管的。
通过这种方式,GraphQL 是连接 REST(以及其他 数据源!)的强大桥梁,它将应用程序的所有数据绑定在一起。GraphQL API 充当这些数据源之上的层,提供单个接口,通过该接口可以同时查询多个数据源。
随着所有 操作 的 字段 解析完毕,数据会被组装成一个格式良好的 JSON 对象,该对象的形状与 查询 完全相同。
服务器将该对象分配给 HTTP 响应正文的 data
键,现在该返回了,回到我们的应用程序。
回到客户端
我们的客户端会收到包含其所需数据的响应,并将该数据传递给合适的组件以进行渲染。
这就是 GraphQL 操作 的流程!
现在我们已经从宏观层面了解了从客户端到服务器再回到客户端的完整流程,我们花点时间深入研究故事中的两个部分: GraphQL 服务器 的结构,以及 GraphQL 操作 的结构。
GraphQL 服务器的结构
GraphQL 服务器 是所有魔法发生的地方。让我们更深入地了解其组成组件。
模式
GraphQL 模式 是类型和 字段 的集合,它们构成了在 GraphQL 服务器 中使用数据的所有操作的全面图景。这里不存储任何实际数据;只有实时数据将符合的形状的基本骨架。(想想蓝图!)
模式定义语言(SDL)
GraphQL 模式 拥有自己的语言,称为 模式定义语言,或 SDL。
我们将简要介绍 SDL 的语法,但这并不是本课程的目的!在下一课中,我们将看到我们使用的 GraphQL 服务器 框架 Strawberry 如何让我们在 Python 中实现 GraphQL,而无需担心 SDL 语法的具体细节。但是,熟悉 SDL 仍然很有帮助,因为它将是 API 和客户端应用程序团队在讨论模式时使用的通用语言。
让我们看一个模式示例。
type Fruit {name: String!quantity: IntaverageWeight: FloathasEdibleSeeds: Booleannutrients: [String]}
Fruit
类型是 对象类型 的一个示例。我们使用 type
关键字定义一个 对象类型,然后是对象名称,最后是花括号。在花括号内,我们定义了与该类型关联的 字段。
一个 字段 以字段名称开头,后面跟着冒号 (:
) 以及该 字段 的类型。在上面的示例中,Fruit
类型中的所有字段都是 标量 类型。
在 GraphQL 中可用的 标量类型 是 String
、Int
、Float
、Boolean
和 ID
。这些类似于任何编程语言中的 标量 类型。方括号 ([]
) 表示 List
类型。
我们可以将模式可视化为一个 图,一个节点和边的数据模型。每个 对象类型 或 标量 类型都是一个节点,而每个关系(对象的 字段)都是两个节点之间的边。
以下是 Python 类型映射到 GraphQL 类型的方式:
Python 类型 | GraphQL 类型 |
---|---|
str | String |
int | Int |
float | Float |
bool | Boolean |
strawberry.ID | ID |
list[str] | [String] |
在 可空性 方面,GraphQL 使用感叹号 (!
) 来表示 不可空(或 必填) 的 字段。在类型后面添加感叹号。
相反,在 Python 中,所有类型 默认情况下 都是不可空的。可空类型使用 T | None
或 Optional[T]
(在旧版本的 Python 中)来定义。
字段 也可以返回 对象类型。例如,在下面的模式中,我们有一个 Vendor
类型,它包含一个 fruitCatalog
字段,它返回一个 Fruit
类型的列表。我们也可以在 Fruit
类型中添加一个名为 soldBy
的新 字段,它返回一个 Vendor
类型。
type Fruit {name: String!quantity: IntaverageWeight: FloathasEdibleSeeds: Booleannutrients: [String]soldBy: Vendor}type Vendor {name: String!fruitCatalog: [Fruit]}
这就是我们真正开始看到 图 在 GraphQL 中发挥作用的地方:当我们对类型之间的关系进行建模和遍历时。
为了利用这个 图,我们需要一个进入图的入口点。
入口点
一个 GraphQL 操作(客户端发送给 GraphQL 服务器 的内容)可以是 查询、变异 或 订阅。一个 查询 读取 数据,一个 变异 更改 数据,而一个 订阅 监听实时流数据。
所有这三种 操作 都映射到模式中相应的类型:Query
、Mutation
和 Subscription
。让我们以 查询 为例。
type Query {mostPopularFruit: Fruit}
我们可以将 字段 视为 Query
类型中的 我们可以询问的内容 的列表。从我们的 GraphQL API 获取。类似地,Mutation
类型是 我们可以对我们的 GraphQL API 执行的操作 的列表。
解析器函数
对于 GraphQL 模式 中的每种类型和 字段,我们都需要定义一个 解析器函数。这是一个可以检索特定 字段 的数据的函数。这些函数可以访问各种 数据源:数据库、REST API,甚至文本文件或 JSON!
解析器 对于模式中 字段 的解析器函数遵循模式的层次结构。这意味着 name
和 quantity
在 Fruit
类型上的 字段 的解析器函数是属于 Fruit
类的方法。这使得我们的 解析器 函数与模式一样井井有条。
GraphQL 操作的结构
旅程始于从客户端发送的 GraphQL 操作。我们已经描述了 GraphQL 操作 为 "定义 选择集 的 字段 的字符串 [客户端] 需要"。当我们编写此 操作 时,我们使用模式作为参考指南,以了解我们可以访问的类型和 字段,以及它们如何相互关联。
我们知道,一个 GraphQL 操作 可以是 查询、变异 或 订阅。让我们看看 查询 的示例可能是什么样子的:
query GetMostPopularFruit {mostPopularFruit {namehasEdibleSeedssoldBy {name}}}
我们已经可以看到,模式是如何被用作此 查询 的参考。
首先,我们以 GraphQL 操作 的类型开头,在本例中是 query
,后面跟着我们选择的 操作名称,GetMostPopularFruit
,然后是花括号。在里面,我们可以开始添加 字段 来自 Fruit
类型:name
、hasEdibleSeeds
、soldBy
。由于 soldBy
是一个返回 Vendor
类型的 字段,我们也从该类型中添加 字段,例如 name
。
从视觉上看,我们也可以将其视为遍历 图。
在本课程中,我们将使用一种名为 Apollo Sandbox Explorer 的工具,它可以帮助我们轻松地构建查询,而无需了解我们应该遵循的语法的细节。
练习
将项目从此框拖动到上面的空白处
问题
订阅
屏幕截图
查询
更改
连接
关键要点
- 有三种类型的 GraphQL 操作: 查询、变异 和 订阅. 一个 查询 读取 数据,一个 变异 更改 数据,一个 订阅 监听实时流式数据。
- The GraphQL schema 是一个类型和 字段 的集合,它们构成了对 GraphQL 服务器中所有可用数据的全面描述。它是用 模式定义语言 (SDL) 编写的。
- 一个 解析器 函数检索我们模式中特定 字段 的数据。这些函数可以访问各种 数据源: 数据库、REST API,甚至文本文件或 JSON。这些数据源不需要位于 GraphQL 服务器 中。
下一步
本课程主要介绍如何构建一个 GraphQL 服务器,所以让我们开始吧!是时候了解 Strawberry 了。
分享您对本课的疑问和评论
本课程目前处于
您需要一个 GitHub 帐户才能在下方发布内容。还没有? 在我们的 Odyssey 论坛中发布。