XMLHttpRequest と fetch の違い
構文的な違いではなく挙動的に違いがあるのか知りたい。 特に、XMLHttpRequest にできて、fetch にできないことがあるのかが気になっている。
以下、XMLHttpRequest は XHR と略す。
結論
XHR にできて、fetch にできないことはほとんどないと言って良さそう。
XHR にあって fetch がサポートしてない機能もあるけど、他の API と組み合わせれば(コードが複雑になる可能性はあるが)再現可能。
ただ、IE では fetch は使えないので、そこだけ注意が必要。(その場合 polyfill 使う必要あり)
fetch と jQuery.ajax() の違い
MDN より引用。 jQuery.ajax() = XHR と読み替えてもよいと思う(ソースコードは この辺)
https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch
fetch の仕様は jQuery.ajax() とは主に二つの点で異なっています。
- fetch() から返される Promise は レスポンスが HTTP 404 や 500 を返して HTTP エラーステータスの場合でも拒否されません。代わりに (ok ステータスが false にセットされて) 正常に解決し、拒否されるのはネットワークのエラーや、何かがリクエストの完了を妨げた場合のみです。
- 既定では、 fetch はサーバーとの間で cookies を送受信しないため、サイトがユーザーセッションの維持に頼っている場合は未認証のリクエストになります (cookie を送るには、認証情報の init オプションを設定しておく必要があります)。 2017年8月25日に、既定の認証情報のポリシーが same-origin に変更になり、 Firefox は 61.0b13 から変更しました。
:qmark: Ajax(XHR)の場合はいつでも cookie 送るということ?
:amark: XHR では同一オリジンなら自動で cookie が送られ、クロスオリジンの場合は fetch と同じように xhr.withCredentials = true;
が必要(構文はちょっと違うけど)、なので cookie に関する挙動は fetch とあんまり変わらないはず
- 参考 URL
「fetch xmlhttprequest difference」 でググった結果
XMLHttpRequest vs the Fetch API: What’s Best for Ajax in 2019?
👆 の記事が良さそうだったのでまとめてみる(他の記事は構文的な違いの言及ばかりだった)
以下、XHR を全て fetch に置き換えられない理由。
Browser Support
IE の全てのバージョンで fetch はサポートされていない。
Cookieless by Default
XMLHttpRequest とは異なり、Fetch のすべての実装が Cookie を送信するわけではないので、アプリケーションの認証に失敗する可能性があります。
って書いてあるけど、これは上述の通り 2017年8月25日 に fetch でも 既定の認証情報のポリシーが same-origin に変更になって同一オリジンには cookie 送られるようになったし、クロスオリジンに cookie 送るには XHR でも fetch でもオプションが必要なので、変わらないと思う。
Errors Are Not Rejected
404 Page Not Foundや500 Internal Server ErrorのようなHTTPエラーは、Fetch Promiseを reject する原因にはならず
.catch()
は決して実行されません。これは通常、response.ok ステータスが false に設定された状態で解決します。 reject はリクエストが完了できない場合にのみ発生します。
だから、fetch だとエラーハンドリングが複雑になるよ、という話。
Timeouts Are Not Supported
fetch はタイムアウトをサポートしていないって話。
Aborting a Fetch
fetch の中断、数年前までできなかった、けど今は AbortController 使えばできるとのこと。
No Progress
fetch では progress events をサポートしてないので、進捗状況が分からないって話。
XMLHttpRequest vs the Fetch API?
XHR の方が低レベルの API なので単純なリクエストなら fetch の方が扱いやすい。(XHR の場合はラッパー関数が必要になる場合が多い)
結論、用途によって fetch でも XHR でも好きな方選べばいいが、プログレスバーを要求するような IE のクライアントがある場合は fetch だとキツい。(一応 polyfill もある けど)
axios と fetch の違い
Axios or fetch(): Which should you use?
LogRocket が axios と fetch の比較記事を書いてたのでまとめる(axios は内部的には XHR 使ってる)
Response timeout
タイムアウトの話題、axios ならオプションつけるだけで簡単に設定できる。 こちらの記事では fetch でも AbortController と setTimeout 使えば実装できるよ、と書いてある。
Automatic JSON data transformation
JSON データの変換を axios なら自動でやってくれるけど fetch は response.json()
しないといけないので一ステップ余分にかかるね、という話。
HTTP interceptors
HTTP インターセプタ機能が axios にはデフォルトでついてる。 fetch もグローバルな fetch メソッドを上書きすれば実装は可能。
Download progress
XHR にあった onprogress ハンドラが fetch にはないが、 fetch の場合も ReadableStream を使えば一応プログレスバーを実装可能。 axios の場合は他ライブラリと組み合わせればさらに簡単に実装できる。
Simultaneous requests
複数のリクエストを同時に行うには axios の場合は axios.all()
メソッドを使用する。
fetch の場合も組み込みの Promise.all()
使えば可能。
Conclusion
上述の通り axios の機能は全て fetch でも再現可能なので、ネイティブ API にこだわるならば、fetch 使ってもいい。
結論、好きな方使ったらよい。
メモ
- Ajax リクエスト = XHR、Ajax リクエスト ≠ fetch ということでよい?
- see. https://developer.mozilla.org/ja/docs/Glossary/AJAX
- 社の有識者に聞いたところ「厳密にいうと違うけど、みんな Ajax を非同期でのデータ取得ぐらいの意味合いで使ってる」とのこと