<p>apollo-link-error 向调用者返回错误</p>

创建于 2019-04-15  ·  17评论  ·  资料来源: apollographql/apollo-link

所以我使用 Apollo-link-error 来管理 auth 和 admin 全局错误。 但是如果我使用它,我的承诺中的 catch 方法不会返回错误。

看起来好像所有错误都通过 apollo-link-error 并且它们没有传递回调用者方法。

有没有办法将错误返回给调用者,以便我可以在本地管理一些错误和全局管理一些错误?

最有用的评论

我找到了解决方案,有点奇怪,但它是:

这仅打印消息

  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

所有17条评论

我的应用程序中有同样的问题。 我想捕获错误链接中的所有错误(例如,我可以记录它们)但我也想将它们转发给原始调用者并在那里处理它们,因为它们可能包含需要向用户显示的自定义错误消息.

我的代码:

  • 在提供者中:
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的参数,因此我不会有数据或错误并将errorsnull也不是 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 的建议取出graphQLErrorsgraphQLErrors是一个空数组. 我只能访问默认消息“错误:网络错误:响应不成功:收到状态代码 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} />}

正如我所说,这种方法非常不合理,但目前正在努力解决:

  1. 即使响应具有非 200 状态代码,通常也能够处理 UI 中的 graphql 错误
  2. 特别能够将错误从 apollo-link-error 配置传递给调用组件,以便在 UI 中呈现

这种方法编码的问题:这只是将数组中的最后一个 GQL 错误写入缓存,因此它不能同时支持多个 GQL 错误。 这应该很容易管理,通过构建错误数组并将其存储在缓存中,但您必须定义本地模式/解析器来执行此操作,或者可能只是 JSON.stringify 将其存储在缓存为字符串。 您还需要在成功时清除缓存中的 currentGraphError,而不仅仅是将布尔值设置为 false。

希望它可以帮助某人!

另外,如果有帮助,请注意 errorPolicy 当前不适用于 useMutation 钩子,这是一个错误,最近在此 PR 中得到解决: https :

开发人员在这方面有任何进展吗?

此页面是否有帮助?
0 / 5 - 0 等级