Fetch APIでデータを取得する

## はじめに
ReactやNext.jsを学習中、APIエンドポイントからデータを取得する方法として、ブラウザに標準で組み込まれているFetch APIを利用しました。
色々調べてみて実装できたので、過程で得た知識をまとめてみたいと思います。
（備忘録です）

## 目次
[Fetch APIについて](#fetch-apiについて)
[Fetch APIを用いたデータ取得](#fetch-apiを用いたデータ取得)
[エラーハンドリングについて](#エラーハンドリングについて)
[async/await構文で書き直してみる](#asyncawait構文で書き直してみる)
[終わりに](#終わりに)
[参考文献](#reference)

## Fetch APIについて
MDNから引用
> フェッチ API は（ネットワーク越しの通信を含む）リソース取得のためのインターフェイスを提供しています。 XMLHttpRequest と似たものではありますが、より強力で柔軟な操作が可能です。

https://developer.mozilla.org/ja/docs/Web/API/Fetch_API

指定したURLに対してHTTPリクエストを送信してリソースを取得するインターフェースで、Fetch APIが出る前はXMLHttpRequestを利用したリソース取得が主流だったようです。

## Fetch APIを用いたデータ取得
※[JSON Placeholder](https://jsonplaceholder.typicode.com/)をエンドポイントとして利用しています。
```javascript
fetch('https://jsonplaceholder.typicode.com/posts/1', {
	method: 'GET', // HTTPメソッドとしてGETを指定
})
	.then((res) => res.json())
	.then((data) => console.log(data));

// console.log()で出力された内容
// {
// 	"userId": 1,
// 	"id": 1,
// 	"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
// 	"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
// }
```

Fetch APIは、第1引数に取得するリソースのURLを指定し、第2引数にはHTTPリクエストのメソッドなどのオプションを指定できます。
メソッドのデフォルトはGETになるので、GETを利用する場合は省略が可能です。

```javascript
fetch('https://jsonplaceholder.typicode.com/posts/1') // GETメソッドを利用する場合は省略可能
	.then((res) => res.json()) // JSONとして解析した結果をresolveするPromiseを返す
	.then((data) => console.log(data));
```

取得したリソースに対してjsonメソッドでパースし、そのデータを最終的にconsole.logで出力しています。

GETメソッド以外のオプションについては以下を参照してください。

https://developer.mozilla.org/ja/docs/Web/API/fetch#parameters

## エラーハンドリングについて
例えば通信エラーなどでリソースが取得できなかった場合はcatchメソッドを利用してエラーを捕捉し、エラーの内容をconsole.errorなどで出力することが可能です。

```javascript
fetch('https://jsonplaceholder.typicode.com/posts/1')
	.then((res) => res.json())
	.then((data) => console.log(data))
	.catch((error) => console.error(error)); // エラーをキャッチしてコンソールで出力
 ```

ただし、Fetch API は通信そのものがエラー（ネットワーク障害など）にならない限りステータスコードが200番台以外でもHTTPエラーは拒否されないという特徴があります。
ですので上記コードだと、404や500のようなエラーについてはエラーとして捕捉することができず、thenメソッドでつないでいるconsole.log(data.userId)でundefinedが出力されてしまいます。

```javascript
fetch('https://jsonplaceholder.typicode.com/posts/xxx')
	.then((res) => res.json())
	.then((data) => console.log(data.userId)) // undefined
	.catch((error) => console.error(error));
 ```

これを防ぐために、Responseオブジェクトのokプロパティを利用して、リクエストが成功したかどうかを判定します。

https://developer.mozilla.org/ja/docs/Web/API/Response/ok

Response.okプロパティは、HTTPレスポンスステータスが成功を示す200〜299の範囲内である場合にtrueを返します。
このプロパティをチェックすることで、成功以外のステータスコードに対してエラーを投げることができます。

```javascript
fetch('https://jsonplaceholder.typicode.com/posts/1')
	.then((res) => {
		// ステータスコードが200-299の範囲かどうかをチェック
		if (!res.ok) {
			throw new Error(res.statusText); // ResponseのstatusTextを用いて例外を投げる
		}
		return res.json(); // 問題なければJSONとして解析
	})
	.then((data) => console.log(data.userId))
	.catch((error) => console.error(error));
 ```

## async/await構文で書き直してみる
```javascript
const asyncFunction = async () => {
	try {
		const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
		if (!res.ok) throw new Error(res.statusText);

		const data = await res.json();
		console.log(data);
	} catch (error) {
		console.error(error);
	}
};

asyncFunction();
 ```
async/await構文に書き直すとより直感的でわかりやすいコードになりました。

## 終わりに
今回はGETメソッドのみを利用したデータの取得でしたが、今後他のメソッドやオプションを利用したり、axiosなどのライブラリを利用する場合にはまたまとめてこの記事を更新したいと思います。
（このFetch APIを調べてようやく非同期処理についてちょっとずつ理解できた感じがします...）

## 参考文献
https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch

https://www.webdesignleaves.com/pr/jquery/fetch-api-basic.html