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

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

让我们看一个模式示例。

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

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

以字段名称开头,然后是冒号 (:),最后是该 的类型。在上例中,Fruit 类型中的所有字段都是 类型。

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

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

Diagram of the Fruit schema

以下是 C# 类型如何映射到 类型:

C# 类型GraphQL 类型
stringString
intInt
doubleFloat
boolBoolean
string, int, longID
List<string>[String]

可空性 方面, 使用感叹号 (!) 来表示 非空(或 必需

相反,在 C# 中,所有类型默认都是非空类型。可空类型用 ? 表示。

也可以返回 。例如,在下边的模式中,我们有一个 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 类型中的 我们可以请求的 内容列表,类似地,Mutation 类型是 我们可以对 GraphQL 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 操作。一个 
 
 读取数据。一个突变 
 
 数据。一个 
 
 监听实时流数据。

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

  • 变化

  • 连接

  • 问题

  • 查询

  • 订阅

  • 屏幕截图

关键要点

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

接下来

本课程是关于构建一个 ,所以让我们开始吧!准备好一杯热饮,准备好,是时候来认识 Hot Chocolate 了。

上一个

分享你关于本课的问题和评论

本课程目前处于

beta
.你的反馈有助于我们改进!如果你卡住了或感到困惑,请告诉我们,我们会帮助你。所有评论都是公开的,必须遵循 Apollo 行为准则。请注意,已解决或已解决的评论可能会被删除。

你需要一个 GitHub 帐户才能在下面发布。没有帐户? 改为在我们的 Odyssey 论坛上发布。