初めに
絶賛ダイエット中の技術開発部の村上(@pipopotamasu)です。
一時期コロナ太りで60kg近くまで増えた体重を52kg台に落とすことに成功しました🚀
普段会社ではideagramや新規プロダクトのフロントエンド部分を開発しています。
私が所属する開発チーム内ではGraphQLを採用しており、フロントエンドではそのクライアントライブラリとしてapollo-clientを利用しております。
今までエラーハンドリングを雰囲気でやってきた戒めをこめて、今日はapollo-clientのerror policyについて書こうと思います。
apollo-clientのエラーについて
error policyを説明する前に、apollo-clientの2種類のエラータイプを紹介します。それはGraphQL errorsとnetwork errorsです。
GraphQL errors
名前の通りGraphQLに関連するエラーです。
例えば…
- queryやmutationのシンタックスエラー
- Schemaの型定義と違っていたときのバリデーションエラー
- リゾルバ内部で発生したエラー
などなどです。このようなエラーが起きた場合、以下のようなレスポンスbodyで返ってきます。
{
"data": null,
"errors": [
{
"message": "err msg",
"locations": [{ "line": 2, "column": 3 }],
"path": ["someMutation"],
"extensions": {}
}
]
}
慣習的にこれらのエラーは、200のHTTPステータスコードで返すようGraphQL serverライブラリで実装されていることが多いです。
そしてGraphQL errorsにはpartial data(もしくはpartial response)という概念があります。
上記のGraphQLのレスポンス例では、dataプロパティはnullになっていますが、GraphQLエラーが発生したからといって必ずしもnullになるわけではありません。GraphQLエラーは起こっているけど、何かしら返却されているdataをpartial dataといいます。
GraphQLの仕様に説明や例があるのでよろしければご覧ください。
http://spec.graphql.org/June2018/#sec-Errors
network errors
400系や500系のHTTPステータスコードが返ってくるようなエラーです。
例えば…
- サーバーからの応答がない
- リクエストしているエンドポイントが存在しない
これらの例から分かる通り、このnetwork errorsはGraphQL特有のエラーではありません。
apollo-clientのerror policyの挙動を理解する上で、この2種類のエラーがあるということを念頭に入れる必要があります。
apollo-clientのerror policyについて
さて、apollo-clientのerror policyとは一体なんなのでしょうか?
ざっくり言うと、「エラー発生時のレスポンスに含まれる、errorsフィールドとdataフィールドの値をどう扱うか」を決めるものになります。
例えば以下のようにapollo-clientが提供するhooksメソッドの返り値にはdata, errorオブジェクトが含まれます。
const { data, error } = useQuery(gqlQuery);
const [fn, { data, error }] = useLazyQuery(gqlQuery);
const [fn, { data, error }] = useMutation(gqlQuery);
error policyはエラー発生時のAPIコールのレスポンスをどのようにdata, errorオブジェクトに伝達するかを決めるわけです。
error policyにはnone, ignore, allの3種類あり、それぞれエラー発生時の挙動に違いがあります。
none (default)
- GraphQL errorsの場合はerror.graphQLErrorsにエラー内容が格納される。
- network errorsの場合はerror.networkErrorにエラー内容が格納される。
- dataオブジェクトはundefinedになる ※。
ignore
- GraphQL errorsの場合はerrorはundefinedになる。
- network errorsの場合はerror.networkErrorにエラー内容が格納される。
- dataオブジェクトにはpartial dataがあればpartial dataが格納される。なければundefinedになる ※。
all
- GraphQL errorsの場合はerror.graphQLErrorsにエラー内容が格納される。
- network errorsの場合はerror.networkErrorにエラー内容が格納される。
- dataオブジェクトにはpartial dataがあればpartial dataが格納される。なければundefinedになる ※。
※ fetchPolicyによってはcacheされているデータが入る
これらを表にまとめるとこんな感じになります。
error policyの使い分けと注意点
今までerror policyに関する説明とふるまいの違いについて説明してきましたが、これを踏まえた上で簡単ですがどのように使い分けたらよさそうなのかまとめてみました。
none
- エラー発生時はユーザにデータを見せたくない場合に使う
all
- エラー発生時でも極力ユーザにデータを見せたい場合に使う
ignore
- エラーを無視したい時に使う
- ただし無視できるのはGraphQL errorsのみでnetwork errorsは無視されない
ignoreに関しては注意が必要なので太字で記載してみました。
終わりに
フロントエンド開発をしているときerrorPolicyによる細かな挙動をよく忘れ、確認するのに時間がかかってしまうのでこの記事の表を作ってみました。もし他の誰かが僕のようなerror policy迷子になってしまった場合、この表を活用していただけたら幸いです。
VISITS Technologiesではフロントエンド、Rails、Goエンジニアなどなど一緒に働く仲間を募集しております。
もしご興味があれば、カジュアル面談も行っているので気軽にお声がけください!
■ 募集ポジションはこちら
https://www.wantedly.com/companies/visitsworks/projects
参考