そのため、Apollo-link-errorを使用して認証および管理のグローバルエラーを管理しています。 しかし、それを使用すると、promiseの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
を呼び出すと、 then
引数として未定義が返されるため、データもエラーも発生せず、 errors
をnull
設定しても効果がないことに注意してください。私は実際にエラーを読み取る必要があるため、
@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} />}
私が言ったように、このアプローチはかなり不合理ですが、現在解決に取り組んでいます:
コード化されたこのアプローチの問題:これは、配列内の最後のGQLエラーをキャッシュに書き込むだけなので、同時に複数のGQLエラーをサポートしていません。 これは、エラーの配列を構築し、それをキャッシュに保存することで、かなり簡単に管理できるはずですが、これを行うにはローカルスキーマ/リゾルバーを定義する必要があります。または、JSON.stringifyして保存する必要があります。文字列としてキャッシュします。 また、ブール値をfalseに設定するだけでなく、成功時にキャッシュ内のcurrentGraphErrorをクリアする必要があります。
それが誰かを助けることを願っています!
また、役立つ場合は、errorPolicyが現在useMutationフックで機能しないことに注意してください。これはバグであり、最近このPRで対処されました: https :
開発者からのこれに関する進展はありますか?
最も参考になるコメント
私は解決策を見つけました、ちょっと奇妙ですが、それは次のとおりです:
これはメッセージだけを印刷します
しかし、これはエラーの全内容を出力します
この問題は解決できると思います
@Nosherwan @romucci @Sceat @lbrdar