https://zenn.dev/takepepe/articles/fetch-error-convolution
「データ取得で try...catch」とは、以下の様なものを指します。
try {
const data = await fetchSomething();
// 正常系レスポンスの処理
} catch (err) {
if (isFetchError(err)) {
// 異常系レスポンスの処理
}
}
理由はつぎのとおりです。
要約すると、データ取得時は常にこの様に書きたい、という話です。useSWR・useQuery や apollo/client でお馴染みのインターフェイスです。
const { data, err, status } = await fetchSomething();
if (data) // 正常系レスポンスの処理
if (err) // 異常系レスポンスの処理
レスポンスを型定義で表すと、この様なものになります。
type Res<T, K> = {
data?: T;
err?: K;
status: number;
};
eslint の no-unused-expressions
で以下のミスはすぐに気付きますが、any に握りつぶされている中間コードがもしあれば、catch 行きになる可能性が拭いきれません。
try {
const data = await fetchSomething();
// 参照ミスなどで例外がthrowされる
a.b.c;
} catch (err) {
if (isFetchError(err)) {
// 異常系レスポンスの処理
}
// ReferenceError でここに着地する
}
こういった、データ取得とは関係ない例外と同列で catch 句ハンドリングしてしまうと、catch 句の肥大化につながりかねません。HttpError は開発者にとって想定範囲内なので、データ取得関数内部で整形し、畳み込んでおきたいです。
理由としてはこれが一番大きいです。データ取得関数が全てRes
の様なレスポンスを返すことが確約されていれば、
Promise.all
での取り回しが格段に楽になります。