如何在我的 Vue Graphql 组件中使用错误并让其他错误在全局范围内处理?
Posted
技术标签:
【中文标题】如何在我的 Vue Graphql 组件中使用错误并让其他错误在全局范围内处理?【英文标题】:How Do I consume errors in my Vue Graphql component and let other errors be handled globally? 【发布时间】:2021-06-21 06:32:17 【问题描述】:我们将 Vue 与 apollo 一起使用,但我很难正确处理错误。
这是我们的组件
<template>
<div v-if="product">
<router-view :key="product.id" :product="product" />
</div>
<div v-else-if="!this.$apollo.loading">
<p>Product is not available anymore</p>
</div>
</template>
<script>
import productQuery from "@/graphql/product.graphql";
export default
name: "ProductWrapper",
props: ["productId"],
apollo:
product:
query: productQuery,
variables()
return
productId: this.productId,
;
,
,
,
;
</script>
如果产品不再可用,我们在后端提供三个选项:
a)后端可以发送null
而不会出错
b)send an error object as part of the data with unions
c) 使用 apollo 发送一些错误扩展,以便在客户端进行错误处理
选项 a) 似乎是一个奇怪的选项 选项 b) 对于我们的用例来说太复杂了。 所以我决定选择c):
在我们的后端,我们使用 apollo 错误扩展来发送一些适当的错误代码供客户端处理。
data:
errors: [
"message": "NOT_FOUND",
"locations": ...,
"path": ...
"extensions":
"details": [],
"errorCode": "NOT_FOUND",
"message": "NOT_FOUND",
"classification": "DataFetchingException"
]
一切正常,因为产品结果为 null,因为没有发送数据,只是一个错误。 但是 vue-apollo 正在将它记录到 console.error 中。我不希望任何日志记录到 console.error 因为用户在他的浏览器中看到一个红色标记。但是如果没有其他人处理过这个错误,我希望它在 console.error 中弹出。
我可以在三个地方添加错误处理:
-
查询定义中的error()
$error() 所有查询的默认处理程序
ErrorLink
ErrorLink 似乎是错误的地方,因为只有组件中的查询知道 NOT_FOUND 不是致命的,但有时会发生。 $error 也是如此
那我怎么说:这个错误可能会发生,我已经为此做好了充分的准备。所有其他错误应由 ErrorLink 处理。如何使用组件中的错误?
【问题讨论】:
【参考方案1】:我对 vue-apollo 错误处理的概述。
SmartQuery 错误处理程序
文档:https://apollo.vuejs.org/api/smart-query.html
error(error, vm, key, type, options) 是一个钩子,当有 错误。 error 是带有 graphQLErrors 的 Apollo 错误对象 属性或 networkError 属性。 vm 是相关组件 实例。 key 是智能查询键。类型是“查询”或 '订阅'。 options 是最终的 watchQuery 选项对象。
未记录:如果您返回 false
,则错误处理将停止,并且不会调用默认错误处理程序(Apollo Provider)。如果您返回 true
或不返回任何内容(又名 undefined
),则会调用默认错误处理程序。
代码示例
export default
name: "ProductWrapper",
props: ['productId'],
apollo:
product:
query: productQuery,
variables()
return
productId: this.productId
,
error(errors)
console.log("Smart Query Error Handler")
console.log(errors.graphQLErrors)
return false;
VueApolloProvider 错误处理程序
文档: https://apollo.vuejs.org/api/apollo-provider.html
所有智能查询和订阅的全局错误处理程序
重要提示:这不适用于突变。
未记录:当智能查询的错误处理程序返回 false
代码示例
const apolloProvider = new VueApollo(
defaultClient: apolloClient,
errorHandler: (errors) =>
console.log("Provider errorHandler")
console.log(errors)
);
VueApolloProvider $error 特殊选项(无用)
文档 https://apollo.vuejs.org/guide/apollo/special-options.html
$error 在默认处理程序中捕获错误(有关智能查询,请参阅错误高级选项>)
代码示例(错误)
const apolloProvider = new VueApollo(
defaultClient: apolloClient,
defaultOptions:
error(errors)
console.log("Provider $error")
console.log(errors)
);
这是我的第一次尝试,但它会在安装组件时调用并为我们提供完整的组件。见https://github.com/vuejs/vue-apollo/issues/126
代码示例(可以吗?)
const apolloProvider = new VueApollo(
defaultClient: apolloClient,
defaultOptions:
$error()
return (errors) =>
console.log("Provider $error handler")
console.log(errors.graphQLErrors)
,
,
);
这样调用 $error 函数。 但它就像默认的 errorHandler 一样被调用(见上文)。文档似乎是错误的。所以这个方法对我来说似乎没什么用。正如您在此调试屏幕截图中所见,它的使用方式与其他错误处理程序一样:
错误链接
文档: https://www.apollographql.com/docs/react/data/error-handling/#advanced-error-handling-with-apollo-link
代码示例
import onError from "apollo-link-error";
const errorHandler = onError(( networkError, graphQLErrors ) =>
console.log("Link onError")
console.log( graphQLErrors, networkError)
)
const link = split(
// split based on operation type
(query) =>
const definition = getMainDefinition(query);
return definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
,
wsErrorHandler.concat(wsLink),
errorHandler.concat(httpLink)
);
重要:在任何其他 ErrorHandler 之前调用它,它适用于查询、订阅和突变
突变捕获
文档 https://apollo.vuejs.org/guide/apollo/mutations.html
代码示例 1
async submit()
await this.$apollo.mutate(
mutation: productDeleteMutation,
variables:
productId: this.product.id
,
).catch((errors) =>
console.log("mutation .catch error")
console.log(errors)
)
代码示例 2 你也可以使用 try/catch:
async submit()
try
await this.$apollo.mutate(
mutation: productDeleteMutation,
variables:
productId: this.product.id
,
)
catch (errors)
console.log("mutation try/catch error")
console.log(errors)
唯一可以调用的其他处理程序是 onError ErrorLink(见上文),它将在捕获错误处理之前调用。
vue 处理带有 errorCaptured 的突变
将此生命周期钩子添加到您的组件以捕获来自突变的错误。
errorCaptured(err, vm, info)
console.log("errorCaptured")
console.log(err.graphQLErrors)
return false
文档:https://vuejs.org/v2/api/#errorCaptured
更多链接:https://medium.com/js-dojo/error-exception-handling-in-vue-js-application-6c26eeb6b3e4
它仅适用于突变,因为智能查询的错误由 apollo 自己处理。
vue 全局 errorHandler 的变异错误
你可以有一个 vue 默认的错误处理程序来捕获来自突变的 graphql 错误
import Vue from 'vue';
Vue.config.errorHandler = (err, vm, info) =>
if (err.graphQLErrors)
console.log("vue errorHandler")
console.log(err.graphQLErrors)
;
它仅适用于突变,因为智能查询的错误由 apollo 自己处理。
文档 https://vuejs.org/v2/api/#errorHandler
window.onerror
vue 之外的错误可以用纯 javascript 处理
window.onerror = function(message, source, lineno, colno, error)
if (error.graphQLErrors)
console.log("window.onerror")
console.log(error.graphQLErrors)
;
这不适用于 vue 组件内部或外部的突变、查询或订阅,因为这些是由 vue 或 apollo 本身处理的(如果未处理,则会打印到 console.err)
文档 https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror
总结
同时捕获突变和查询错误的唯一方法是使用 ApolloLink 的 onError。服务器、网络和身份验证错误应该在那里被捕获,因为这些不是特定于任何操作的。
补充说明
探讨如何处理后端的错误
https://blog.logrocket.com/handling-graphql-errors-like-a-champ-with-unions-and-interfaces/
【讨论】:
以上是关于如何在我的 Vue Graphql 组件中使用错误并让其他错误在全局范围内处理?的主要内容,如果未能解决你的问题,请参考以下文章