<p>apollo-link-errorは呼び出し元にエラーを返します</p>

作成日 2019年04月15日  ·  17コメント  ·  ソース: apollographql/apollo-link

そのため、Apollo-link-errorを使用して認証および管理のグローバルエラーを管理しています。 しかし、それを使用すると、promiseの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を呼び出すと、 then引数として未定義が返されるため、データもエラーも発生せず、 errorsnull設定しても効果がないことに注意してください。私は実際にエラーを読み取る必要があるため、

@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ハンドラーで何かを実行できます。 ただし、これらのエラーは実際の呼び出しの約束には渡されません。
私は非同期関数を使用しているので、 'then'の代わりにawaitキーワードを使用しています。これは、trycatchブロック内にあります。
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

これをドキュメントに追加するのはどうですか?

申し訳ありませんが、上記の解決策は機能しません。 link-errorのgraphqlErrorsを最初の呼び出し元に送り返す方法の完全な例を推測します。

私の場合、エラーが発生すると、次のApolloQueryResultオブジェクトはonErrorでコンソール化されたエラーの詳細を取得しません。 試行中の一部...呼び出しを取り巻くキャッチ。 サーバーから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を受信しました」にしかアクセスできません。 400ステータスコードはApolloの終止符であるため、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;
}

私のサーバーは200 + graphqlエラーであるはずの400を_常に_返すので、これはすべてのミューテーションで必要なのでグローバルになります(私はそれについて少し塩辛いです)...

したがって、ここで重要なことは、すべてのコンポーネントの変更で、Apolloからの未処理の例外を防ぐ空のonErrorコールバックを使用することです。成功したら、キャッシュ内の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. 具体的には、UIでレンダリングするために、エラーをapollo-link-error構成から呼び出し元のコンポーネントに渡すことができます。

コード化されたこのアプローチの問題:これは、配列内の最後のGQLエラーをキャッシュに書き込むだけなので、同時に複数のGQLエラーをサポートしていません。 これは、エラーの配列を構築し、それをキャッシュに保存することで、かなり簡単に管理できるはずですが、これを行うにはローカルスキーマ/リゾルバーを定義する必要があります。または、JSON.stringifyして保存する必要があります。文字列としてキャッシュします。 また、ブール値をfalseに設定するだけでなく、成功時にキャッシュ内のcurrentGraphErrorをクリアする必要があります。

それが誰かを助けることを願っています!

また、役立つ場合は、errorPolicyが現在useMutationフックで機能しないことに注意してください。これはバグであり、最近このPRで対処されました: https

開発者からのこれに関する進展はありますか?

このページは役に立ちましたか?
0 / 5 - 0 評価