fetchとaxiosって使い分けてる？

## はじめに
株式会社アシストエンジニアリング、エンジニアのkinopyです。
今回から弊社所属のエンジニアが、各々興味がある分野や業務での気づきを定期的に投稿していきたいと思います！
 
突然ですが、フロントエンドのAPIはどのように叩いてますか？
おそらくTypeScript(JavaScript)を触るほとんどの方は”fetch” or “axios”が第一の選択肢ですよね（XMLHttpRequestはもうはるか昔ですね）。
ちなみに自分はfetch派です。
フロントとバックエンドを分けて開発する最近のウェブ開発の手法では、API通信は避けて通れないものです。そんなAPI通信における自分が考えるベストな実装方法をこの機会にまとめてみます。
## fetch (FetchAPI)ってなに？
fetch (FetchAPI)は、JavaScriptの標準APIとして提供されているHTTP通信のメソッドです。
さらっと「JavaScriptの標準APIとして提供」と書きましたが、これめちゃ重要です（理由は後述）。
```javascript
fetch('https://api.example.com/data')
	.then(res => res.json())
	.then(data => console.log(data))
	.catch(error => console.error('Error:', error));
```
簡単なGETリクエストはこんな感じで書けます。
大きな特徴としては、fetchで返されたJSONデータは、はじめに`res`で受け取ってからJSONを抽出しなくてはいけません。
また、POSTリクエストやヘッダーの設定等をしっかり行うとなると、少しだけ複雑になります。
```javascript
fetch('https://api.example.com/data', {
	method: 'POST',
	headers: {
		'Content-Type': 'application/json'
	},
	body: JSON.stringify({ key: 'value' })
})
	.then(res => res.json())
	.then(data => console.log(data))
	.catch(error => console.error('Error:', error));
```
fetchの利点は、軽量かつブラウザネイティブのため追加のライブラリが不要な点です。
実際自分がfetch派なのは、この「ライブラリを追加しない」という点がかなり大きいです。
※ライブラリを追加しない＝特定のバージョンに依存しない＝保守しやすい
ただし、エラーハンドリングが少し面倒だったり、インターセプター機能（HTTPリクエストやレスポンスの前後に特定の処理を追加するための仕組み）がないなどのデメリットもあります。
【注意点】
`fetch()`  から返されるプロミスは、レスポンスが HTTP 404 や 500 を返す HTTP エラーステータスの場合でも拒否されません。
なので、404エラーなどを適切にエラーハンドリングする場合、
```javascript
fetch('https://api.example.com/data')
	.then((res)  =>  {
		response.ok  
			? res => res.json() 
			: console.log("エラーです！");  
	})
	.then(data => console.log(data))
	.catch(error => console.error('Error:', error));
```
のように`response.ok`でリクエストコードによる処理の場合分けが必要です。
※対して後述のaxiosでは404や500エラーは拒否されるため、場合分けは不要です
## axiosってなに？
一方、axiosはPromiseベースの第三者が提供するHTTPクライアントライブラリです。fetchと同様にAPI通信を簡単に行えますが、より多機能で使いやすいです。
```javascript
import axios from 'axios';
axios.get('https://api.example.com/data')
	.then(res => console.log(res.data))
	.catch(error => console.error('Error:', error));
```
POSTリクエストの場合は↓
```javascript
axios.post('https://api.example.com/data', {
	key: 'value'
})
	.then(response => console.log(response.data))
	.catch(error => console.error('Error:', error));
```
axiosの利点は、何よりもその多機能さです。
例えば、リクエストやレスポンスのインターセプター機能を使えば、↓のようにリクエスト前後に特定の処理を挟むことが簡単にできます。
また、fetchと比較したときにresponse.dataで直接JSONデータが取得でき、抽出の必要がありません。
  
```javascript
axios.interceptors.request.use(config => {
	console.log('Request made with ', config);
	return config;
}, error => {
	return Promise.reject(error);
});
axios.interceptors.response.use(response => {
	console.log('Response received', response);
	return response;
}, error => {
	return Promise.reject(error);
});
```
  
## 【結論】どちらを使うべき？
では、fetchとaxios、どちらを使うべきか？
ここまで読んでいただいた方はなんとなくお察しの通り、
結論としては、ケースバイケースだと思います。
 
 簡単に表にまとめます。
 
|  | fetch | axios |
| :---: | :---: | :---:|
| import | 不要（標準機能） | 必要 |
| 多機能さ | △ | ◎ |
| JSONの抽出 | 必要 | 不要 |
| 直感的 | ◯ | ◎ |

※処理速度は、通常の記述量であれば無視できるくらいの差だと思うので、省略しています（あえて言えば軽量なfetchの方がわずかに速いです）
 **・ライブラリに依存したくない、機能は最低限あればいい場合**
　→標準APIであり、軽量、シンプルなfetchが適しています
**・直感的に書きたい、多機能さを求める場合**
　→複雑なリクエストやレスポンス処理などを行いたい場合にはaxiosが便利です
例えば、↓の場合ではaxiosの方が適しています。
 
```javascript
// 一度に複数のリクエストを行う場合
const getUser = axios.get('https://api.example.com/user');
const getPosts = axios.get('https://api.example.com/posts');
axios.all([getUser, getPosts])
	.then(axios.spread((user, posts) => {
		console.log('User:', user.data);
		console.log('Posts:', posts.data);
	}));
```

## 追記
コメントいただき、axios v1.7.0 からはAxiosのリクエストをネイティブのFetch APIを使用して処理するために `Fetch Adapter` として fetch が提供され、`axios`で`fetch`機能が使えるようになったみたいです。

参考サイト↓
https://qiita.com/youtoy/items/2411de0d8081acbad5c0
https://github.com/axios/axios?tab=readme-ov-file#-fetch-adapter

これにより以下のような記述が可能となりました。
```javascript
import axios from 'axios';

const fetchAxios = axios.create({
  adapter: 'fetch'
});

const { data } = fetchAxios.get(url);
```
  
## 終わりに
いかがでしたでしょうか。
fetchとaxios、どちらも利点があるため使う用途や場面に応じて選択してもらえればと思います。個人的にしばらくは基本fetchで、記述が煩雑になってきたり機能が不足したらaxiosを使うかなーと思います。
## 採用拡大中！
アシストエンジニアリングでは一緒に働くフロントエンド、バックエンドのエンジニア仲間を大募集しています！
少しでも興味ある方は、カジュアル面談からでもぜひお気軽にお話ししましょう！
お問い合わせはこちらから↓
https://official.assisteng.co.jp/contact/
## 参考
- https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch
- https://axios-http.com/docs/api_intro