处理操作错误
Apollo 客户端在执行你的GraphQL 服务器上的操作时可能会遇到各种错误。 Apollo 客户端帮助你根据错误类型处理这些错误,使得在发生错误时能够向用户显示适当的信息。
错误类型
在远程服务器上执行GraphQL操作会导致GraphQL 错误或网络错误。
GraphQL 错误
这些是与服务器端执行操作相关的错误。
- 语法错误(例如,一个查询格式不正确)
- 验证错误(例如,查询中包含了一个不存在的模式字段)
- 解析器错误(例如,在尝试填充查询字段时发生错误)
如果发生语法错误或验证错误,由于无效,服务器不会执行该操作。如果发生解析器错误,服务器仍可以返回部分数据。
了解有关GraphQL错误的信息,请访问Apollo Server 文档。
当发生GraphQL错误时,您的服务器将其包含在其errors
数组中,以响应Apollo Client:
Apollo Client随后将这些错误添加到您使用useQuery调用返回的error.graphQLErrors
数组(或您使用的任何操作钩子)。
如果GraphQL错误阻止Apollo Server执行您操作,它将返回一个4xx
状态码。Apollo Server在解析器错误发生但响应仍然包含部分数据时,返回200
状态码。
部分数据与解析器错误
一个可能引发解析器错误的操作可能会返回部分数据。这意味着您请求的数据中某些(但不是全部)数据已包含在服务器响应中。Apollo Client默认情况下会忽略部分数据,但您可以通过设置GraphQL错误策略来覆盖此行为。
网络错误
这些是在与GraphQL服务器通信时遇到的错误,通常会导致4xx
或5xx
状态码(没有数据)的响应。
当发生网络错误时,Apollo Client会将它添加到您的useQuery调用返回的error.networkError字段(或您所使用的任何操作钩子)。
您可以使用Apollo Link为您的应用程序添加重试逻辑和其他高级网络错误处理。
GraphQL错误策略
如果一个GraphQL操作产生了一个或多个解析器错误,您的服务器响应可能仍然会在data
字段中包含部分数据:
{"data": {"getInt": 12,"getString": null},"errors": [{"message": "Failed to get string!"// ...additional fields...}]}
默认情况下,Apollo Client会丢弃部分数据,并为您的useQuery调用返回的error.graphQLErrors数组填充内容(无论您使用的是哪个钩子)。您可以通过为您的操作定义一个错误策略来替代这些部分结果。
Apollo Client支持以下操作错误策略:
策略 | 描述 |
---|---|
无 | 如果响应包含GraphQL错误,它们将返回在error.graphQLErrors 上,即使服务器在其响应中返回了data ,响应的数据也将设置为undefined 。这意味着网络错误和GraphQL错误会产生相似的反应形式。这是默认错误策略。 |
忽略 | graphQLErrors 被忽略(error.graphQLErrors 不会填充),任何返回的data 都会被缓存并像没有错误发生一样渲染。 |
全部 | 同时填充data 和error.graphQLErrors ,这样您就可以渲染部分结果和错误信息。 |
设置错误策略
在您提供的操作钩子(例如useQuery
)的选项对象中指定错误策略:
const MY_QUERY = gql`query WillFail {badField # This field's resolver produces an errorgoodField # This field is populated successfully}`;function ShowingSomeErrors() {const { loading, error, data } = useQuery(MY_QUERY, { errorPolicy: "all" });if (loading) return <span>loading...</span>;return (<div><h2>Good: {data.goodField}</h2><pre>Bad:{" "}{error.graphQLErrors.map(({ message }, i) => (<span key={i}>{message}</span>))}</pre></div>);}
本例使用all
错误策略在适用时渲染部分数据和错误信息。
使用Apollo Link进行高级错误处理
Apollo Link库允许您配置执行GraphQL操作时出现的高级错误处理。
作为推荐的第一步,您可以将Apollo Link添加到您的链式链接中,该链式链接接收错误详情并相应地处理它们。
下面的示例向ApolloClient
构造函数中传递了一个包含两个链接的链式链接:
- 一个用于检查服务器响应中的
graphQLErrors
或networkError
的onError
链接。它会记录发现的错误详情。 - 用于将每个GraphQL操作发送到您的服务器的
HttpLink
。- 这是链的终止链接。
重试操作
Apollo Link帮助您重试失败的操作,这些操作可能通过后续尝试解决。我们根据发生错误类型推荐不同的链接:
- 用于
GraphQL错误
的onError
链接。 - 用于
网络错误
的RetryLink
。
关于GraphQL错误
当返回GraphQL错误时,onError
链接可以基于返回的GraphQL错误类型重试失败的操作。例如,当使用基于令牌的认证时,您可能想要在令牌过期时自动处理重新认证。
要重试一个操作,在您的onError
函数中返回forward(operation)
。以下是一个示例:
onError(({ graphQLErrors, networkError, operation, forward }) => {if (graphQLErrors) {for (let err of graphQLErrors) {switch (err.extensions.code) {// Apollo Server sets code to UNAUTHENTICATED// when an AuthenticationError is thrown in a resolvercase "UNAUTHENTICATED":// Modify the operation context with a new tokenconst oldHeaders = operation.getContext().headers;operation.setContext({headers: {...oldHeaders,authorization: getNewToken(),},});// Retry the request, returning the new observablereturn forward(operation);}}}// To retry on network errors, we recommend the RetryLink// instead of the onError link. This just logs the error.if (networkError) {console.log(`[Network error]: ${networkError}`);}});
如果您重试操作 仍然发生错误,这些错误不会传递到您的onError
链接,以防止无限循环操作。这意味着onError
链接只能重试特定操作一次。
如果您不想重试操作,您的onError链接的函数应该返回空值。
网络错误
为了重试遇到网络错误的操作,我们建议向您的链接链中添加一个RetryLink
。此链接允许您配置重试逻辑,例如指数退避和尝试次数总数。
有关RetryLink
的文档。
onError
链接选项
请参阅onError
的API参考。