【JavaScript】fetchメソッド

## 1. fetchメソッドとは
下記ドキュメントからの引用（https://developer.mozilla.org/ja/docs/Web/API/Window/fetch）
```
fetch() は Window インターフェイスのメソッドで、ネットワークからリソースを取得するプロセスを開始し、レスポンスが利用できるようになったら履行されるプロミスを返します。
```
すごく簡単にいうと***非同期通信でリクエストを発行し、そのレスポンスを取得できる関数***らしい:smiley:

fetchメソッドを理解するためには、まず非同期通信について理解する必要がありそうなので、１つずつ丁寧に理解していければと思います、、

## 2.　非同期通信ってなに？
**＜同期通信＞**
まず前提に同期通信についてですが、同期通信とは「１つの作業が終わるまで次の作業に進めない」という通信の仕組みです。

例えをだすと、ウェブサイトにて「最新ニュースを見る」ボタンを押したとします。このとき裏ではサーバーに「最新ニュースをください」というリクエストが送られます。そして、そのリクエストに対するサーバーの返答が返ってくるまでブラウザは他の処理をとめて待ち続けるといったイメージです。

**＜非同期通信＞**
非同期通信とは、サーバーにデータをリクエストしたとき、その返事を待たずに別の作業を進められる仕組みのことを言います。

先程の同期通信の例えを使用すると、同期通信では「最新ニュースを取得する」ボタンを押し、返答が返ってくるまでは他の処理はできませんでしたが、非同期通信では、「最新ニュースをください」というリクエストが送られ返答を待っている間にページのスクロールや他のボタンをクリックすることが可能です。

ここまでみると、非同期通信はすごく便利だと感じますね。
fetchメソッド以外にもAjaxのXMLHttpRequest(XHR)やWebSocket,Axios,jQuery.ajax()などを使用することで非同期通信は実現できるのですがなぜfetchメソッドが良いのかを次に説明できればと思います。

## 3.fetchメソッドを使用する理由
色々理由はあるかと思いますが、特にこれというところでいくと、
①シンプルな構文であることと
②Promiseベースの設計であること
かと思います。

①に関してはAjaxのXHRと比較してみると分かりやすいです。
```java: Fetchメソッド
fetch ('https://example.com/api/data')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error, error));
```
指定したURLにGETリクエストを送信
↓
最初のthenメソッドではリクエストの返答をうけとり、JSON形式のデータに変換
↓
2つ目のthenメソッドでは、前のステップで得たJSONデータをdataとして受け取りコンソールに出力
↓
最後はエラーが発生した場合、そのエラー取得しコンソールにエラーメッセージを表示

```java: XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/api/data', true);
xhr.onreadystatechange = function() {
    if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status === 200) {
            console.log(JSON.parse(xhr.responseText));
        } else {
            console.error('Error:', xhr.status);
        }
    }
};
xhr.send();
```

上記は同じことをしている処理になりますが、fetchメソッドのほうが大分と見やすいことがわかります。

②Promiseベースの設計
Promiseベースの設計とは非同期処理をを扱う際に、Promiseオブジェクトを利用して、処理の結果やエラーを管理するる方法です。
具体的な説明はこの方の記事がとても分かりやすかったです（https://qiita.com/cheez921/items/41b744e4e002b966391a）
Promiseベースの利点としては、可読性やエラーハンドリングがシンプルになることかと思います。

## 4. 簡単に実装してみた
```java: sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Fetch API Example</title>
</head>
<body>
    <h1>Fetch API の練習</h1>
    <button id="fetchData">データを取得する</button>

    <script>
        document.getElementById('fetchData').addEventListener('click', function() {
            // Fetchメソッドで外部APIからデータを取得
            fetch('https://jsonplaceholder.typicode.com/posts/1')
                .then(response => {
                    // レスポンスが正常かどうかを確認
                    if (!response.ok) {
                        throw new Error('Network response was not ok');
                    }
                    return response.json(); // JSON形式に変換
                })
                .then(data => {
                    console.log('取得したデータ:', data); // データをコンソールに表示
                })
                .catch(error => {
                    console.error('Fetchエラー:', error); // エラーが発生した場合の処理
                });
        });
    </script>
</body>
</html>

```
実際の画面で、データを取得するボタンを押したときの動作は下記でした

![スクリーンショット 2024-09-26 111138.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669426/ef8703bc-4c7c-e7fc-067d-bc09e4915c09.png)

URLにリクエストを送り、dataオブジェクトでJSON形式のデータを取得しているという形になります。

## 5.まとめ
「非同期通信は難しいのではないか？」と思い、避けたくなることもありましたが、意外と理解を深めていくうちに、その便利さを実感しました。また、基本的な内容を把握していれば、簡単にコードを書くことができそうだと感じました。今後は、これをサーバーと組み合わせた形でさらに理解を深めていきたいと思います。

PS：記事をかいていると最後の方になるにつれて流れが変になるのを、どうしたらいいかアドバイスあればおしえてください:cry: