所以我使用 Apollo-link-error 来管理 auth 和 admin 全局错误。 但是如果我使用它,我的承诺中的 catch 方法不会返回错误。
看起来好像所有错误都通过 apollo-link-error 并且它们没有传递回调用者方法。
有没有办法将错误返回给调用者,以便我可以在本地管理一些错误和全局管理一些错误?
我的应用程序中有同样的问题。 我想捕获错误链接中的所有错误(例如,我可以记录它们)但我也想将它们转发给原始调用者并在那里处理它们,因为它们可能包含需要向用户显示的自定义错误消息.
我的代码:
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
console.log(`[GraphQL error]: ${message}, Location: ${locations}, Path: ${path}`);
},
);
}
});
const client = new ApolloClient({
link: authLink.concat(errorLink).concat(httpLink),
cache: new InMemoryCache(),
});
loginMutation({ variables: { data } })
.then(({ data, errors }) => {
if (errors) {
// I WANT TO BE ABLE TO READ ERROR MESSAGE HERE SO I CAN DISPLAY IT TO THE USER
} else if (data) {
....
}
});
请注意,调用forward
将无济于事,因为它返回 undefined 作为then
的参数,因此我不会有数据或错误并将errors
为null
也不是 n 选项,因为我实际上需要读取错误。
@lbrdar你有没有找到任何解决方法?
没有😞
@lbrdar这样做的方法不是捕获吗?
loginMutation({ variables: { data } })
.then(({ data, errors }) => {
if (errors) {
// I WANT TO BE ABLE TO READ ERROR MESSAGE HERE SO I CAN DISPLAY IT TO THE USER
} else if (data) {
....
}
}).catch(errors => {
});
@lbrdar @romucci我面临同样的问题。 你们最后解决了吗?
@Nosherwan我刚刚安装了 1.1.11 版,现在一切正常......你也可以检查你的内部承诺(也许你忘记在其他承诺中返回承诺)
@merksam感谢您的评论。
我正在使用与您完全相同的版本。 不幸的是,行为是相同的。
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
console.log(`[GraphQL error]: ${message}, Location: ${locations}, Path: ${path}`);
},
);
}
});
在上面的代码块中,graphQLErrors 被捕获并且可以在 onError 处理程序中做一些事情。 然而,这些错误不会传递给实际的调用承诺。
我正在使用异步函数,所以我使用的是 await 关键字而不是 'then',它位于 try catch 块内。
catch 块捕获错误,但没有传递给它的错误。
有人找到了解决方法吗?
@Nosherwan @prem-prakash 我们能否在聊天中联系某个地方,甚至打个电话,以便我们尝试找出为什么它在我的情况下有效而在你的情况下无效? (如果它仍然相关)
我找到了解决方案,有点奇怪,但它是:
这仅打印消息
updateProfile: function() {
this.$apollo
.mutate({
mutation: UPDATE_PROFILE,
variables: current_user
})
.catch((error) => {
console.log("this prints just the message", error);
});
}
但是这会打印错误的全部内容
updateProfile: function() {
this.$apollo
.mutate({
mutation: UPDATE_PROFILE,
variables: current_user
})
.catch(({ graphQLErrors }) => {
console.log("this prints the full content of 'errors'", graphQLErrors);
});
}
我认为这个问题可以关闭
@Nosherwan @romucci @Sceat @lbrdar
将其添加到文档中怎么样?
抱歉,上面的解决方案不起作用。 我想关于如何将链接错误中的 graphqlErrors 发送回初始调用者的完整示例。
就我而言,当出现错误时,以下 ApolloQueryResult 对象不会获得 onError 中控制台的错误详细信息。 一些在 try ... catch 周围的调用。 无法从服务器获取 graphqlError 详细信息。 只是一个“400错误”..
const gqlResult: ApolloQueryResult<IGReturnData<
IAllDataTypes
>> = await apolloClient.query<IGReturnData<IAllDataTypes>, TVariables>({
query: queryGql,
variables: queryVariables,
errorPolicy: "all",
});
服务器配置:
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
const httplink = new HttpLink({
uri: "/graphql",
credentials: "include",
});
const links = [errorLink, httplink];
export const apolloClient = new ApolloClient({
link: ApolloLink.from(links),
cache: new InMemoryCache({ addTypename: false, fragmentMatcher }),
});
@prem-prakash 谢谢.... 救世主...
这个问题非常顽固。 我无法控制项目中的 graphql 服务器,只能控制客户端。 服务器以正确形状的 graphql 错误进行响应,但状态代码为 400。 在错误链接中,我可以访问graphQLErrors
,但是在组件突变中,当我按照@prem-prakash 的建议取出graphQLErrors
, graphQLErrors
是一个空数组. 我只能访问默认消息“错误:网络错误:响应不成功:收到状态代码 400”。 Apollo 正在破坏来自服务器的人类可读的错误消息(“用户或密码不正确”),因为 400 状态代码是 Apollo 的句号。
有没有人可以成功处理带有错误消息的 400 状态代码响应,并将该消息传递给调用突变的组件的 UI?
好吧,我有一个非常不合理的方法,但它正在起作用:
我在缓存中设置了一个布尔值hasGraphError
,并且还缓存了错误消息。
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(error => {
// log gql error(s)
console.log("[GraphQL error]: ", error);
// cache error
client.writeData({
data: {
hasGraphError: true,
currentGraphError: error.message
}
});
});
}
if (networkError) {
// log network errors
console.log("[Network error]: ", networkError);
}
});
然后在 MutationError 组件中,我查询缓存是否存在错误和错误消息,有条件地呈现 gql 错误或真正的网络错误:
const HAS_ERROR = gql`
query IsGraphErrorPresent {
hasGraphError <strong i="11">@client</strong>
currentGraphError <strong i="12">@client</strong>
}
`;
export default function MutationError({ error }) {
const { data } = useQuery(HAS_ERROR);
const defaultErrorMessage =
"We're having trouble connecting. Please check your internet connection and try again.";
// real network error
if (error && error.message.includes("Failed to fetch")) {
return <Error>{defaultErrorMessage}</Error>;
}
// graph error
if (error && data && data.hasGraphError) {
return <Error>{data.currentGraphError}</Error>;
}
// probably a real server/network error
if (error) {
return <Error>{defaultErrorMessage}</Error>;
}
return null;
}
这将是全局的,因为我在所有突变上都需要它,因为我的服务器 _always_ 返回 400 应该是 200 + graphql 错误(我对此有点咸)...
所以这里重要的是,在每个组件突变时,我使用一个空的 onError 回调来防止来自 Apollo 的未处理的异常,并且在成功时我必须记住重置缓存中的 hasGraphError 布尔值:
const [someMutation, { loading, error, client }] = useMutation(SOME_MUTATION, {
onError() {
// this callback prevents apollo from throwing
// ...unhandled exception on 400 status code
},
onCompleted({ someMutation }) {
client.writeData({
data: {
hasGraphError: false
}
});
}
});
然后突变错误组件将 useMutation 错误作为道具(这既可以确定真实的网络错误,又可以确保我们不会在错误的组件上呈现全局缓存的 gql 错误):
{loading && <Spinner />}
{error && <MutationError error={error} />}
正如我所说,这种方法非常不合理,但目前正在努力解决:
这种方法编码的问题:这只是将数组中的最后一个 GQL 错误写入缓存,因此它不能同时支持多个 GQL 错误。 这应该很容易管理,通过构建错误数组并将其存储在缓存中,但您必须定义本地模式/解析器来执行此操作,或者可能只是 JSON.stringify 将其存储在缓存为字符串。 您还需要在成功时清除缓存中的 currentGraphError,而不仅仅是将布尔值设置为 false。
希望它可以帮助某人!
另外,如果有帮助,请注意 errorPolicy 当前不适用于 useMutation 钩子,这是一个错误,最近在此 PR 中得到解决: https :
开发人员在这方面有任何进展吗?
最有用的评论
我找到了解决方案,有点奇怪,但它是:
这仅打印消息
但是这会打印错误的全部内容
我认为这个问题可以关闭
@Nosherwan @romucci @Sceat @lbrdar