Help us understand the problem. What is going on with this article?

Fetch APIでネットワークエラーも含めてエラーハンドリングする

More than 1 year has passed since last update.

Fetch API をラップした fetchWithErrorHandling を作る

fetch APIを使うにあたって、ネットワークエラーなどのハンドリングを考えると少しエラーハンドリングの順序を工夫しないといけない。結論から言うと、以下のようなコードにすることで例えばChromeの ERR_CONNECTION_REFUSED も含めて拾うことができる。

const handleErrors = (res) => {
  if (res.ok) {
    return res;
  }

  switch (res.status) {
    case 400: throw Error('INVALID_TOKEN');
    case 401: throw Error('UNAUTHORIZED');
    case 500: throw Error('INTERNAL_SERVER_ERROR');
    case 502: throw Error('BAD_GATEWAY');
    case 404: throw Error('NOT_FOUND');
    default:  throw Error('UNHANDLED_ERROR');
  } 
};

const fetchWithErrorHandling = (url, options) =>
  fetch(url, options)
    // 1. ネットワーク周りなどのリクエスト以前の段階でのエラーを処理する
    .catch((e) => { throw Error(e); })
    // 2. サーバサイドで発行されたエラーステータスを処理する
    .then(handleErrors)
    // 3. 以上2つをパスした正常なレスポンスからJSONオブジェクトをパースする
    .then(res => res.json());

重要なポイントなのは handleErrorsAPI側のエラーを拾う前Promise.prototype.catch でネットワークエラーなどの、APIへのリクエスト自体の失敗を拾っておくこと。これが必ず最初にないと、そもそもレスポンスが返されず handleErrors の内部で res を見る処理そのものがエラーになってしまう。

fetchWithErrorHandling を使ってみる

以下は async/await と一緒に fetchWithErrorHandling を使う例。

const unauthorizedRequest = async () => {
    try {
      await fetchWithErrorHandling('https://httpstat.us/401');
    } catch (e) {
      console.log(e); // Error: UNAUTHORIZED
    }
};

unauthorizedRequest();

余談: エラーステータスを例外としてcatchすべきか否か

そもそも論として、APIからのレスポンスとしての404や401を try...catch の中でエラーとしてハンドリングするべきなのか? という点には、議論の余地がある。なぜなら、40x系や50x系のエラーレスポンスをサーバサイドから受け取れているという点で Fetch API は処理を完了しており、アプリケーションとしては正常であるから。

fetchWithErrorHandling は実装上の利便性のためにフロントエンド側のエラーとサーバサイド側のエラーをひとつにまとめて例外として処理しているが、厳密に例外処理を区分する場合には今回の実装は必ずしも適切ではない。

IzumiSy
Elmエンジニャー / https://dev.to/izumisy
https://izumisy.work
fringe81
Fringeは、最新のテクノロジーとプロフェッショナルによるサービスにより、社会課題に仮説を立てて市場に広げていくことで、数十年という長期的なスパンで価値を生み出し続け、より良い世界を創る集団です。 既存の領域に限らず、時流を読み、仮説を生み出し、テクノロジーの力で優れたサービスを生み出し続けます。
https://www.fringe81.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away