0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

response.ok === false と `catch` の違いをメモしておく

0
Posted at

はじめに

fetch() を書くたびに「あれ、catch に入らないのはなんでだっけ」「catch でエラーを拾えているのにステータスコードが見当たらない」という状況になりがちなので、自分用に整理しておきます。

原因は毎回同じで、fetch() が 2 種類のエラーを全く異なるルートで通知するという仕様を忘れているだけなのですが、何度でも忘れます。

結論:「サーバーと通信できたかどうか」の差

いつも最初にこれだけ思い出せれば十分です。

状態 意味
response.ok === false サーバーに到達できた。ただしサーバーがエラーを返した
catch でエラー そもそもサーバーに到達できなかった

この2つを混同すると、デバッグの方向が真逆になります。

1. response.ok === false になる場合(通信は成功)

fetch() はサーバーとの接続が確立して HTTP レスポンスが返ってきた時点で Promise を resolve します。
ステータスコードが 400 や 500 でも「サーバーが答えた」という事実には変わりないので、reject にはなりません。ここをよく忘れます。

response.ok はステータスコードが 200〜299 のときだけ true になるプロパティで、それ以外は false です。

具体的なケース

ステータス 意味 よくある原因
400 Bad Request リクエストの構文・パラメータが誤っている バリデーションエラー
401 Unauthorized 認証が必要、またはトークンが無効 Authorization ヘッダー漏れ
500 Internal Server Error サーバー側でエラーが発生 サーバーのバグ
503 Service Unavailable サーバーがメンテナンス中または過負荷 デプロイ直後、障害

レスポンスボディが存在します
response.ok === false のとき、サーバーはエラーの詳細を JSON やテキストでボディに乗せていることが多いです。await response.json() で読み取れます。

2. catch でエラー(Reject)になる場合(通信が失敗)

サーバーへのリクエストが届かなかったか、受け取れなかったケースです。
fetch() の Promise が reject されて catch ブロックに TypeError が届きます。
HTTP ステータスコードは存在しないので、response.status を見ようとしてもそもそも response オブジェクトがありません。

具体的なケース

種別 発生条件
オフライン 端末がインターネットに接続されていない
DNS エラー ドメイン名が存在しない、または名前解決に失敗した
CORS エラー 別オリジンへのリクエストをブラウザが遮断した(サーバーが許可していない)
タイムアウト サーバーの応答が遅すぎて制限時間を超えた
SSL/TLS エラー 証明書が失効・不正・ドメインが一致しない
リクエストの中断 AbortController.abort() で処理をキャンセルした

CORS エラーは catch に届く
CORS エラーはネットワークエラーとして扱われるので、response.ok ではなく catch で引っかかります。しかも error.message に詳細が出ないのでわかりにくいです。Console に「CORS policy」と出ていたら Network タブを確認してください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?