2. 什么是 GraphQL?
5m

概述

在本课中,我们将

  • 探索客户端请求数据以及 如何检索数据。
  • 了解组成 的组件
  • 了解 语法的基础知识:

GraphQL 操作的流程

我们的应用程序需要为特定页面获取数据。

为了获取这些数据,它会发送一个 到我们的 。应用程序将操作塑造成一个字符串,该字符串定义了其所需的 。然后,它以 HTTP POSTGET 请求的形式将该操作发送到服务器。

Hand-drawn illustration depicting client-land with a browser sending a query to server-land across a network

服务器端

当我们的服务器收到 HTTP 请求时,它首先会提取包含 的字符串。它解析并将其转换为更容易操作的形式:一个称为 的树状结构 AST(抽象语法树)。使用此 AST,服务器可以根据模式中的类型和 验证

如果出现任何错误(例如,请求的 未在模式中定义,或者 格式错误),服务器会抛出错误并将其立即发送回应用程序。

Hand-drawn illustration depicting server-land with the GraphQL server receiving a query and going through the necessary steps

在这种情况下, 看起来没问题,服务器可以“执行”它。这意味着服务器可以继续其处理过程并实际获取数据。服务器会遍历 AST。

对于 中的每个 ,服务器都会调用该字段的 函数。解析器函数的任务是通过从正确的数据源(例如数据库或 REST API)获取正确的数据来“解析”其字段。这些 不一定需要在 内,它们可以是外部托管的。

通过这种方式, 是连接 REST(以及其他 !)的强大桥梁,它将应用程序的所有数据绑定在一起。GraphQL API 充当这些数据源之上的层,提供单个接口,通过该接口可以同时查询多个数据源。

Hand-drawn illustration depicting a resolver function retrieving data from data-land

随着所有 解析完毕,数据会被组装成一个格式良好的 JSON 对象,该对象的形状与 完全相同。

服务器将该对象分配给 HTTP 响应正文的 data 键,现在该返回了,回到我们的应用程序。

Hand-drawn illustration depicting the server returning a response back to the browser in client-land

回到客户端

我们的客户端会收到包含其所需数据的响应,并将该数据传递给合适的组件以进行渲染。

这就是 的流程!

现在我们已经从宏观层面了解了从客户端到服务器再回到客户端的完整流程,我们花点时间深入研究故事中的两个部分: 服务器 的结构,以及 操作 的结构。

GraphQL 服务器的结构

是所有魔法发生的地方。让我们更深入地了解其组成组件。

模式

模式 是类型和 的集合,它们构成了在 中使用数据的所有操作的全面图景。这里不存储任何实际数据;只有实时数据将符合的形状的基本骨架。(想想蓝图!)

模式定义语言(SDL)

拥有自己的语言,称为 模式定义语言,或 SDL

我们将简要介绍 的语法,但这并不是本课程的目的!在下一课中,我们将看到我们使用的 框架 Strawberry 如何让我们在 Python 中实现 GraphQL,而无需担心 SDL 语法的具体细节。但是,熟悉 SDL 仍然很有帮助,因为它将是 API 和客户端应用程序团队在讨论模式时使用的通用语言。

让我们看一个模式示例。

GraphQL 模式示例
type Fruit {
name: String!
quantity: Int
averageWeight: Float
hasEdibleSeeds: Boolean
nutrients: [String]
}

Fruit 类型是 对象类型 的一个示例。我们使用 type 关键字定义一个 ,然后是对象名称,最后是花括号。在花括号内,我们定义了与该类型关联的

一个 以字段名称开头,后面跟着冒号 (:) 以及该 的类型。在上面的示例中,Fruit 类型中的所有字段都是 类型。

中可用的 标量类型StringIntFloatBooleanID。这些类似于任何编程语言中的 类型。方括号 ([]) 表示 List 类型。

我们可以将模式可视化为一个 ,一个节点和边的数据模型。每个 类型都是一个节点,而每个关系(对象的 )都是两个节点之间的边。

Diagram of the Fruit schema

以下是 Python 类型映射到 类型的方式:

Python 类型GraphQL 类型
strString
intInt
floatFloat
boolBoolean
strawberry.IDID
list[str][String]

可空性 方面, 使用感叹号 (!) 来表示 不可空(或 必填) 的 。在类型后面添加感叹号。

相反,在 Python 中,所有类型 默认情况下 都是不可空的。可空类型使用 T | NoneOptional[T] (在旧版本的 Python 中)来定义。

也可以返回 。例如,在下面的模式中,我们有一个 Vendor 类型,它包含一个 fruitCatalog ,它返回一个 Fruit 类型的列表。我们也可以在 Fruit 类型中添加一个名为 soldBy 的新 ,它返回一个 Vendor 类型。

GraphQL 模式示例
type Fruit {
name: String!
quantity: Int
averageWeight: Float
hasEdibleSeeds: Boolean
nutrients: [String]
soldBy: Vendor
}
type Vendor {
name: String!
fruitCatalog: [Fruit]
}

这就是我们真正开始看到 中发挥作用的地方:当我们对类型之间的关系进行建模和遍历时。

Diagram of the Fruit and Vendor relationship

为了利用这个 ,我们需要一个进入图的入口点。

入口点

一个 (客户端发送给 的内容)可以是 查询变异订阅。一个 读取 数据,一个 更改 数据,而一个 监听实时流数据。

所有这三种 都映射到模式中相应的类型:QueryMutationSubscription。让我们以 为例。

GraphQL 模式示例
type Query {
mostPopularFruit: Fruit
}

我们可以将 视为 Query 类型中的 我们可以询问的内容 的列表。从我们的 API 获取。类似地,Mutation 类型是 我们可以对我们的 API 执行的操作 的列表。

解析器函数

对于 中的每种类型和 ,我们都需要定义一个 解析器函数。这是一个可以检索特定 的数据的函数。这些函数可以访问各种 :数据库、REST API,甚至文本文件或 JSON!

对于模式中 的解析器函数遵循模式的层次结构。这意味着 namequantityFruit 类型上的 的解析器函数是属于 Fruit 类的方法。这使得我们的 函数与模式一样井井有条。

GraphQL 操作的结构

旅程始于从客户端发送的 操作。我们已经描述了 为 "定义 的字符串 [客户端] 需要"。当我们编写此 时,我们使用模式作为参考指南,以了解我们可以访问的类型和 ,以及它们如何相互关联。

我们知道,一个 可以是 。让我们看看 查询 的示例可能是什么样子的:

GraphQL 查询示例
query GetMostPopularFruit {
mostPopularFruit {
name
hasEdibleSeeds
soldBy {
name
}
}
}

我们已经可以看到,模式是如何被用作此 的参考。

首先,我们以 的类型开头,在本例中是 query,后面跟着我们选择的 GetMostPopularFruit,然后是花括号。在里面,我们可以开始添加 来自 Fruit 类型:namehasEdibleSeedssoldBy。由于 soldBy 是一个返回 Vendor 类型的 ,我们也从该类型中添加 ,例如 name

从视觉上看,我们也可以将其视为遍历

Diagram traversing the graph using the query

在本课程中,我们将使用一种名为 Explorer 的工具,它可以帮助我们轻松地构建查询,而无需了解我们应该遵循的语法的细节。

练习

当我们的 GraphQL 服务器收到请求时,它会执行哪些操作?
在哪些情况下我们的 GraphQL 服务器会抛出错误?
解析器函数有哪些职责?
当查询成功执行时,GraphQL 服务器返回的对象中包含哪些内容?
GraphQL 操作
有三种类型的 GraphQL 操作。一个 
 
 读取数据。一个变异 
 
 数据。一个 
 
 监听实时流式数据。

将项目从此框拖动到上面的空白处

  • 问题

  • 订阅

  • 屏幕截图

  • 查询

  • 更改

  • 连接

关键要点

  • 有三种类型的 : 查询、. 一个 读取 数据,一个 更改 数据,一个 监听实时流式数据。
  • The schema 是一个类型和 的集合,它们构成了对 GraphQL 服务器中所有可用数据的全面描述。它是用 () 编写的。
  • 一个 函数检索我们模式中特定 的数据。这些函数可以访问各种 : 数据库、REST API,甚至文本文件或 JSON。这些数据源不需要位于 中。

下一步

本课程主要介绍如何构建一个 ,所以让我们开始吧!是时候了解 Strawberry 了。

上一步

分享您对本课的疑问和评论

本课程目前处于

测试版
.您的反馈有助于我们改进!如果您遇到困难或困惑,请告知我们,我们将帮助您。所有评论都是公开的,必须遵守 Apollo 行为准则。请注意,已解决或已处理的评论可能会被删除。

您需要一个 GitHub 帐户才能在下方发布内容。还没有? 在我们的 Odyssey 论坛中发布。