跳至内容

错误处理

任何应用程序,从简单到复杂,都可能遇到各种错误。处理这些错误并尽可能将错误报告给用户以获取信息非常重要。使用 GraphQL 会带来一组新的可能错误,这些错误来自实际的 GraphQL 响应本身。考虑到这一点,以下是一些不同类型的错误

  • GraphQL 错误:GraphQL 结果中的错误,可能与成功数据一起出现
  • 服务器错误:服务器内部错误,阻止成功响应的形成
  • 事务错误:在变异上的 update 等事务操作中的错误
  • UI 错误:在组件代码中发生的错误
  • Apollo Client 错误:核心或相应库中的内部错误

错误策略

fetchPolicy 类似,errorPolicy 允许您控制如何将来自服务器的 GraphQL 错误发送到您的 UI 代码。默认情况下,错误策略将任何 GraphQL 错误视为网络错误并结束请求链。它不会在缓存中保存任何数据,并且会将您的 UI 的 error 属性呈现为 ApolloError。通过更改每个请求的策略,您可以调整 GraphQL 错误在缓存和 UI 中的管理方式。errorPolicy 的可能选项是

  • none:这是与 Apollo Client 1.0 工作方式一致的默认策略。任何 GraphQL 错误都将与网络错误相同,并且响应中的任何数据都将被忽略。
  • ignore:忽略允许您读取与 GraphQL 错误一起返回的任何数据,但不保存错误或将其报告给您的 UI。
  • all:使用 all 策略是通知用户潜在问题同时仍然显示来自服务器尽可能多的数据的最佳方式。它将数据和错误都保存到 Apollo 缓存中,以便您的 UI 可以使用它们。

您可以在每个请求上设置 errorPolicy,如下所示

vue
<script>
export default {
  setup () {
    const { result, loading, error } = useQuery(gql`
      query WillFail {
        badField
        goodField
      }
    `, null, {
      errorPolicy: 'all',
    })

    return {
      result,
      loading,
      error,
    }
  },
}
</script>

<template>
  <div v-if="loading">Loading...</div>
  <div v-else>
    <h2>Good: {{ result.goodField }}</h2>
    <pre>Bad:
      <span v-for="(error, i) of error.graphQLErrors" :key="i">
        {{ error.message }}
      </span>
    </pre>
  </div>
</template>

网络错误

在使用 Apollo Link 时,处理网络错误的能力更加强大。最好的方法是使用 @apollo/client/link/error 来捕获和处理服务器错误、网络错误和 GraphQL 错误。如果您想与其他链接组合使用,请参阅 组合链接

js
import { onError } from '@apollo/client/link/error'

const link = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.map(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
      ),
    )

  if (networkError) console.log(`[Network error]: ${networkError}`)
})

您还可以使用 @vue/apollo-util 包中的 logErrorMessages 函数来格式化浏览器控制台中的错误

js
import { onError } from '@apollo/client/link/error'
import { logErrorMessages } from '@vue/apollo-util'

const link = onError(error => {
  logErrorMessages(error)
})

示例错误

Error log screenshot

如果您使用的是 Webpack 或 Vue CLI,最好只在开发中使用它

js
import { onError } from '@apollo/client/link/error'
import { logErrorMessages } from '@vue/apollo-util'

const link = onError(error => {
  if (process.env.NODE_ENV !== 'production') {
    logErrorMessages(error)
  }
})

这样,在为生产编译项目时,它将被删除。

完整示例

js
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client/core'
import { onError } from '@apollo/client/link/error'
import { logErrorMessages } from '@vue/apollo-util'

const cache = new InMemoryCache()

// HTTP connection to the API
let httpLink = createHttpLink({
  uri: 'http://localhost:4242/graphql',
})

// Handle errors
const errorLink = onError(error => {
  if (process.env.NODE_ENV !== 'production') {
    logErrorMessages(error)
  }
})

export const apolloClient = new ApolloClient({
  cache,
  link: errorLink.concat(httpLink),
})

选项

Error Link 接受一个在发生错误时调用的函数。此函数使用包含以下键的对象调用

  • operation:发生错误的操作
  • response:来自服务器的响应
  • graphQLErrors:来自 GraphQL 端点的错误数组
  • networkError:链接执行或服务器响应期间发生的任何错误

忽略错误

如果您想有条件地忽略错误,可以在错误处理程序中设置 response.errors = null;

js
onError(({ response, operation }) => {
  if (operation.operationName === 'IgnoreErrorsQuery') {
    response.errors = null
  }
})