@@ -6,7 +6,7 @@ permalink: /learn/execution/
6
6
next : /learn/introspection/
7
7
---
8
8
9
- 在验证环节之后, GraphQL 服务端在处理数据,会根据 GraphQL 查询的请求内容生成对应结构的结果,一般情况下会以 JSON 形式返回 。
9
+ 一个 GraphQL 查询在被验证后, GraphQL 服务器会将之执行,并返回与请求的结构相对应的结果,该结果通常会是 JSON 的格式 。
10
10
11
11
GraphQL 不能脱离类型系统处理查询,让我们用一个类型系统的例子来说明一个查询的执行过程,在这一系列的文章中我们重复使用了这些类型,下文是其中的一部分:
12
12
@@ -47,13 +47,13 @@ type Starship {
47
47
}
48
48
```
49
49
50
- 您可以将 GraphQL 查询中的每个字段视为返回下一个类型的上一个类型的函数或方法 。事实上,这正是 GraphQL 的工作原理。每个类型的每个字段都由称为 * resolver* 的函数支持 ,该函数由 GraphQL 服务器开发人员提供。当一个字段被执行时,相应的解析器被调用以产生下一个值 。
50
+ 您可以将 GraphQL 查询中的每个字段视为返回子类型的父类型函数或方法 。事实上,这正是 GraphQL 的工作原理。每个类型的每个字段都由一个 * resolver* 函数支持 ,该函数由 GraphQL 服务器开发人员提供。当一个字段被执行时,相应的 * resolver * 被调用以产生下一个值 。
51
51
52
52
如果字段产生标量值,例如字符串或数字,则执行完成。但是,如果一个字段产生一个对象,则该查询将继续执行该对象对应字段的解析器,直到生成标量值。GraphQL 查询始终以标量值结束。
53
53
54
54
## 根字段 & 解析器
55
55
56
- 每一个 GraphQL 服务端应用的顶层,必有一个类型代表着所有进入 GraphQL API 可能的入口点,我们将他称之为 * Root* 类型或 * Query* 类型。
56
+ 每一个 GraphQL 服务端应用的顶层,必有一个类型代表着所有进入 GraphQL API 可能的入口点,我们将它称之为 ** Root** 类型或 ** Query* * 类型。
57
57
58
58
在这个例子中查询类型提供了一个字段 ` human ` ,并且接受一个参数 ` id ` 。这个字段的解析器可能请求了数据库之后通过构造函数返回一个 ` Human ` 对象。
59
59
@@ -67,7 +67,7 @@ Query: {
67
67
}
68
68
```
69
69
70
- 这个例子使用了 JavaScript 语言,但 GraphQL 服务端应用可以被 [ 多种语言实现] ( /code/ ) 。解析器函数接受 3 个参数:
70
+ 这个例子使用了 JavaScript 语言,但 GraphQL 服务端应用可以被 [ 多种语言实现] ( /code/ ) 。解析器函数接收 3 个参数:
71
71
72
72
- ` obj ` 上一级对象,如果字段属于根节点查询类型通常不会被使用。
73
73
- ` args ` 可以提供在 GraphQL 查询中传入的参数。
@@ -85,9 +85,9 @@ human(obj, args, context) {
85
85
}
86
86
```
87
87
88
- ` context ` 提供了一个数据库访问对象,用来通过查询中传递的参数 ` id ` 来查询数据,因为从数据库拉取数据的过程是一个异步操作,该方法返回了一个 [ Promise] ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise ) 对象,在 JavaScript 语言中 Promise 对象用来处理异步操作,但在许多语言中存在相同的概念,通常称作 * Futures* 、 * Tasks* 或者 * Defferred* 。当数据库返回查询结果,我们就能构造并返回一个新的 ` Human ` 对象。
88
+ ` context ` 提供了一个数据库访问对象,用来通过查询中传递的参数 ` id ` 来查询数据,因为从数据库拉取数据的过程是一个异步操作,该方法返回了一个 [ Promise] ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise ) 对象,在 JavaScript 语言中 Promise 对象用来处理异步操作,但在许多语言中存在相同的概念,通常称作 ** Futures** 、 ** Tasks** 或者 ** Defferred* * 。当数据库返回查询结果,我们就能构造并返回一个新的 ` Human ` 对象。
89
89
90
- 这里要注意的是,只有解析器能感知到 Promise 的进度,GraphQL 查询只关注一个包含着` name ` 属性的 ` human ` 字段是否返回,在执行期间如果异步操作没有完成,则 GraphQL 会一直等待下去,因此在这个环节需要关注异步处理上的优化。
90
+ 这里要注意的是,只有解析器能感知到 Promise 的进度,GraphQL 查询只关注一个包含着 ` name ` 属性的 ` human ` 字段是否返回,在执行期间如果异步操作没有完成,则 GraphQL 会一直等待下去,因此在这个环节需要关注异步处理上的优化。
91
91
92
92
## 不重要的解析器
93
93
@@ -103,9 +103,9 @@ Human: {
103
103
104
104
GraphQL 服务端应用的业务取决于类型系统的结构。在 ` human ` 对象返回值之前,由于类型系统确定了 ` human ` 字段将返回一个 ` Human ` 对象,GraphQL 会根据类型系统预设好的 ` Human ` 类型决定如何解析字段。
105
105
106
- 在这个例子中,对 name 字段的处理非常的清晰,name 字段对应的解析器被调用的时候,解析器回调函数的 obj 参数是在上层回调函数生成的 ` new Human ` 对象。在这个案例中,我们希望 Human 对象会拥有一个 ` name ` 属性可以让我们从 obj 参数中直接读取 。
106
+ 在这个例子中,对 name 字段的处理非常的清晰,name 字段对应的解析器被调用的时候,解析器回调函数的 obj 参数是由上层回调函数生成的 ` new Human ` 对象。在这个案例中,我们希望 Human 对象会拥有一个 ` name ` 属性可以让我们直接读取 。
107
107
108
- 事实上在返回的字段可以直接从对象中获得的时候,大部分 GraphQL 库可以让我们省略定义的步骤,当然这是当我们请求的字段可以直接从上层返回对象中取得并返回的情况 。
108
+ 事实上在返回的字段可以直接从对象中获得的时候,大部分 GraphQL 库可以让我们省略定义的步骤,当然这只适用于我们请求的字段可以直接从上层返回对象中取得并返回的情况 。
109
109
110
110
## 标量强制
111
111
@@ -119,13 +119,13 @@ Human: {
119
119
}
120
120
```
121
121
122
- 请注意,我们的类型系统声明 ` appearsIn ` 字段将返回具有已知值的枚举值,但是此函数返回数字实际上 ,如果我们查看结果,我们将看到正在返回适当的枚举值。这是怎么回事?
122
+ 请注意,我们的类型系统声明 ` appearsIn ` 字段将返回具有已知值的枚举值,但是此函数返回数字!实际上 ,如果我们查看结果,我们将看到正在返回适当的枚举值。这是怎么回事?
123
123
124
- 这是一个强制标量的例子。因为类型系统已经被设定,所以解析器函数的返回值必须符合与类型系统对应的API规则的约束。在这种情况下,我们在的服务器的类定义了一个应该返回枚举值解析器在内部返回了 4、5 和 6 的整数类型,由于 GraphQL 类型系统中将它们表示为枚举值,类型不匹配。因此实际的返回不是 ` [4,5,6] ` 而是 ` [null,null,null] ` ,并提示错误 。
124
+ 这是一个强制标量的例子。因为类型系统已经被设定,所以解析器函数的返回值必须符合与类型系统对应的API规则的约束。在这种情况下,我们在的服务器的类定义了一个应该返回枚举值解析器在内部返回了 4、5 和 6 的整数类型,但是 GraphQL 类型系统中将它们表示为枚举值。
125
125
126
126
## 列表解析器
127
127
128
- 我们已经看到一个字段返回上面的 ` appearsIn ` 字段的事物列表时会发生什么。它返回了枚举值的* 列表 * ,因为这是系统期望的类型,列表中的每个项目被强制为适当的枚举值。让我们看下 ` startships ` 被解析的时候会发生什么?
128
+ 我们已经看到一个字段返回上面的 ` appearsIn ` 字段的事物列表时会发生什么。它返回了枚举值的** 列表 * * ,因为这是系统期望的类型,列表中的每个项目被强制为适当的枚举值。让我们看下 ` startships ` 被解析的时候会发生什么?
129
129
130
130
``` js
131
131
Human: {
@@ -139,15 +139,16 @@ Human: {
139
139
}
140
140
```
141
141
142
- 解析器在这个字段中不仅仅是返回了一个 Promise 对象,它返回一个 Promises * 列表 * 。 ` Human ` 对象具有他们正在驾驶的 ` Starships ` 的 ids 列表,但是我们需要通过这些 id 来获得真正的 Starship 对象。
142
+ 解析器在这个字段中不仅仅是返回了一个 Promise 对象,它返回一个 Promises ** 列表 * * 。 ` Human ` 对象具有他们正在驾驶的 ` Starships ` 的 ids 列表,但是我们需要通过这些 id 来获得真正的 Starship 对象。
143
143
144
- GraphQL 将在并发执行这些 Promise,当执行结束返回一个对象列表后,它将继续并发加载列表中每个对象的 ` name ` 字段。
144
+ GraphQL 将并发执行这些 Promise,当执行结束返回一个对象列表后,它将继续并发加载列表中每个对象的 ` name ` 字段。
145
145
146
146
## 产生结果
147
147
148
- 当每个字段被解析时,结果被放置到键值映射中,字段名称(或别名)作为键值映射的键,解析器的值作为键值映射的值,这个过程从查询字段的底部叶子节点开始返回,直到根查询类型的根字段 。总而言之,这些结构反映了根查询类型 ,然后可以将其发送(通常为 JSON 格式)到请求的客户端。
148
+ 当每个字段被解析时,结果被放置到键值映射中,字段名称(或别名)作为键值映射的键,解析器的值作为键值映射的值,这个过程从查询字段的底部叶子节点开始返回,直到根 Query 类型的起始节点 。总而言之,这些结构反映了根 Query 类型 ,然后可以将其发送(通常为 JSON 格式)到请求的客户端。
149
149
150
150
让我们最后一眼看看原来的查询,看看这些解析函数如何产生一个结果:
151
+
151
152
``` graphql
152
153
# { "graphiql": true }
153
154
{
0 commit comments