错误处理
ⓘ 注意
从 4.0.0 版本开始,Apollo Kotlin 提供了一种在解析时自动处理错误的方法。 字段 仅在错误目的上可空,也可在 Kotlin 中生成非空。您可以在 "处理 nullability" 页面 中了解更多信息。
ApolloResponse
ApolloResponse
包含三个重要的 字段:
exception
包含任何抓取错误。errors
包含任何 GraphQL 错误。data
包含任何返回(可能是部分)的数据。
使用 ApolloResponse.data
检查服务器是否返回数据:
if (response.data != null) {// Handle (potentially partial) data} else {// Something wrong happenedif (response.exception != null) {// Handle fetch errors} else {// Handle GraphQL errors in response.errors}}
这也适用于调用 toFlow()
(例如,与 订阅)和 watch()
(与 规范化缓存)。
apolloClient.subscription(subscription).toFlow().collect { response ->if (response.data != null) {// Handle (potentially partial) data} else {if (response.exception != null) {// Handle fetch errors} else {// Handle GraphQL errors in response.errors}}}
如果您更喜欢抛出异常,可以使用 dataOrThrow()
来获取非空数据:
val data = apolloClient.query(ExampleQuery()).execute().dataOrThrow()// data is non-null
不同类型的错误
每次您使用 Apollo Kotlin(或任何其他GraphQL 客户端)执行 GraphQL 操作时,都可能发生两种类型的错误:
- 网络请求错误:由于与您的 GraphQL 服务器 通信出错,没有收到 GraphQL 响应。这可能是 SSL 错误、由于您的应用处于离线状态而产生的套接字错误,或 500 或任何其他 HTTP 错误。当发生网络请求错误时,不返回数据,
response.exception
是非空的。 - GraphQL 错误:收到了 GraphQL 响应(HTTP 200),其中包含非空 errors 字段。这意味着服务器无法完全处理 query。如果服务器能够处理查询的一部分,则响应可能包括部分数据。
网络请求错误
网络请求错误发生在无法获取 GraphQL 响应时。它们可能有各种各样的原因(非详尽列表):
- 应用离线或没有访问网络的权限。
- 发生 DNS 错误,无法查找主机。
- 发生 SSL 错误(例如,服务器证书不受信任)。
- 连接已关闭。
- 服务器用非成功的 HTTP 状态码响应。
- 服务器没有用有效的 JSON 响应。
- 响应 JSON 不满足模式且无法解析。
- 请求指定为 CacheOnly 但数据未缓存。
- 等等...
你可以根据异常在 response.exception
GraphQL 错误
GraphQL 错误发生在成功获取了 GraphQL 响应但包含 GraphQL 错误的情况下。在这种情况下,响应可能包含部分数据。
例如,以下查询使用无效的 id
来查找一个 Person
query FilmAndPersonQuery {film(id: "ZmlsbXM6MQ==") {title}person(id: "badId") {name}}
服务器将返回以下响应
{"data": {"film": {"title": "A New Hope"},"person": null},"errors": [{"message": "Cannot find person with id 'badId'","path": ["person"]}]}
person
是空的:
// there was an error fetching dataprintln(response.data?.person) // null// read the error from response.errorsprintln(response.errors?.first()?.message) // "Cannot find person with id 'badId'"// partial data is also returnedprintln(response.data?.film?.title) // "A New Hope"// exception is nullprintln(response.exception) // null
这允许尽可能显示数据量,而无需进行新的网络往返。
由于 GraphQL 将错误和语义上的空值都建模为可空字段,你必须检查 errors
来确定字段是错误还是真正的空值。
例如,一个人可能没有飞船
{"data": {"person": {"starship": null}}}
在这种情况下, starship
是一个真正的空值,而不是错误。
真值表
exception | data | errors | meaning |
---|---|---|---|
空 | 空 | 空 | 不合规服务器,如果 data 是空的,则至少应该有一个错误 |
空 | 空 | 存在 | 发生了 GraphQL 请求错误或图字段错误向上冒泡。 |
空 | 存在 | 空 | 完整数据已接收。 |
空 | 存在 | 存在 | 接收到部分数据以及存在字段错误。 |
存在 | 空 | 空 | 发生了 fetch 错误。 |
存在 | 空 | 存在 | 🙅♂️不可能。 |
存在 | 存在 | 空 | 🙅♂️不可能。 |
存在 | 存在 | 存在 | 🙅♂️不可能。 |