Javascriptの非同期処理とfetch APIについて学ぶ

現在学習中のJavascriptで新しくfetch APIについて学習をしたため、復習も兼ねて投稿します。

## 目次
① まず初めに（非同期処理について ※ 説明長め）

② fetch APIとは

③ 実際に使ってみた 

## まず初めに（非同期処理について）
Javascriptには非同期処理というものがあり、fetch APIは非同期処理の一部であるため、まずは非同期処理について説明します。

### 非同期処理とは？？

簡潔に言うと非同期処理とは、
<font color="red">実行した処理が完了するのを待たず、次の処理を実行する動きのこと</font>
です。

逆に同期処理とは、
<font color="blue">実行した処理が完了してから次の処理に順番に進んでいく動きのこと</font>
になります。


実際に同期処理と非同期処理の違いについて、実際のコードと結果を記入すると以下のようになります。

※以下の処理は@tokky_se様の投稿を参考に記載しております。
　実際の処理の動きも確認されたい場合は、こちらの投稿がとても分かりやすい為ご確認することをお勧め致します。

https://qiita.com/tokky_se/items/2312952976cd1055d8b8


#### 同期処理
```javascript
console.log(1);

console.log(2);

console.log(3);

/*
 * １、２、３が順番に表示される。
 */
```

#### 非同期処理
```javascript
setTimeout(function(){console.log(1)}, Math.random()*1000);
setTimeout(function(){console.log(2)}, Math.random()*1000);
setTimeout(function(){console.log(3)}, Math.random()*1000);

/*
 * １、２、３がバラバラの順番で出力される
 */
```


### どのような場面で使用されるのか

上記のように短くて軽い処理ではあまり非同期処理は目立たないかもしれませんが、
実行するメソッドの処理が複雑で重い処理の場合に非常に利用されます。

例えば、以下のような処理があった場合、
```javascript
let total = 0;

function add(){
    console.log("処理を実行中");

    for(let i = 0; i < 10000; i++){

        total += i;
    }
    console.log(total);
    console.log("処理が完了しました");
}

console.log("処理を開始します");

add();

console.log("処理の完了が確認できました。次の処理に入ります。");

console.log("処理を終了します");

// 出力結果
/*
 * 処理を開始します
 * 処理を実行中
 * 
 * :（何秒か待ち）
 * 
 *  500500
 * 処理の完了が確認できました。次の処理に入ります。
 * 処理を終了します。
 */
```
このfor文の処理がとてつもなく長い処理の場合、同期処理ではこの処理が終了するまでの間、他の処理を行うことができません。
そこで出てくるのが非同期処理になります。非同期処理を利用した場合、以下のような処理が可能です。
```javascript
let total = 0;

function add(){
    console.log("処理を実行中");

    for(let i = 0; i < 10000; i++){

        total += i;
    }
    console.log(total);
    console.log("処理が完了しました");
    console.log("処理を終了します。");
}

console.log("処理を開始します");

setTimeout(add, 60000);

console.log("先にこちらの処理に入ります。");

console.log(4 + 5);

// 出力結果
/*
 * 処理を開始します
 * 先にこちらの処理に入ります。　　(この間setTimeoutのカウントが実行中)
 * 9　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　(この間setTimeoutのカウントが実行中)
 * 
 * (setTimeoutが実行されてから1分後)
 * 
 * 処理を実行中
 * 500500
 * 処理が完了しました
 * 処理を終了します。
 */
```

非同期処理が実行後は一度その処理は完了するまでの間に次の処理を実行し、非同期処理が終了したら実行結果を出力していることがわかります。

この原理を利用した一番身近な例をあげると、Googleマップが該当します。
地図をスクロールするたびに全てのページを再度読み込み、その処理が完了するまで処理ができないのではとても使い勝手が悪いです。そんな時にこの非同期処理を利用すれば、リアルタイムでデータを読み込むため、画面表示してる状態で操作も受け付けている状態で更新できます。


## fetch APIとは
そんな非同期処理を利用できるAPIの一つが、fetch APIになります。
このメソッドは、非同期処理でデータの送受信をすることができます。

#### 基本的な記法
```javascript
// fetchメソッドで指定されたリソース（url）の非同期通信結果をResponseオブジェクトを含むPromiseオブジェクトで返す 
   fetch('指定のURL')

// thenメソッドでPromiseオブジェクト経由で渡されたResponseオブジェクトを処理する
  .then(response => response.json())

// 渡された応答データを処理する
  .then(data => console.log(data));
```
fetchメソッドはプロミス（promise）オブジェクトというものを返します。
※プロミス（オブジェクト）とは
>非同期処理の最終的な完了もしくは失敗を表すオブジェクト。
>
>JavaScriptは非同期言語であるため、一つ前の実行に時間がかかった場合、実行完了をまたずに次の処理が行われてしまう。
そのため、処理を待機することや、その結果に応じて次の処理をすることお約束するものがプロミスオブジェクトである。
>
※

詳細は参考文献にてしっかり説明をして下さっているサイトのリンクをご覧ください。


## 実際に使ってみた
今回はvanillawebprojects.comというサイトを利用し、fetch APIを用いて通貨換算ツールを作成しました。

#### ソースコード

```javascript
'use strict'

const currencyEl_one = document.getElementById('currency-one');

const amountEl_one = document.getElementById('amount-one');

const currencyEl_two = document.getElementById('currency-two');

const amountEl_two = document.getElementById('amount-two');

const rateEl = document.getElementById('rate');

const swap = document.getElementById('swap');


function calculate() {

    const currency_one = currencyEl_one.value;
    const currency_two = currencyEl_two.value;

    fetch("https://open.exchangerate-api.com/v6/latest")

    .then(res => res.json())

    .then(data => {
        console.log(data);

        const rate = (data.rates[currency_two] / data.rates[currency_one]).toFixed(2);
        rateEl.innerText = `1 ${currency_one} = ${rate} ${currency_two}`;
        amountEl_two.value = (amountEl_one.value * (rate)).toFixed(2);
    });
}

// Event Listener
currencyEl_one.addEventListener('change', calculate);
amountEl_one.addEventListener('input', calculate);
currencyEl_two.addEventListener('change', calculate);
amountEl_two.addEventListener('input', calculate);

swap.addEventListener('click', () => {

    const temp = currencyEl_one.value;

    currencyEl_one.value = currencyEl_two.value;

    currencyEl_two.value = temp;

    calculate();
});

calculate();
```

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- 
        Internet Explorerを使用している人が、『利用できる中で互換性のモードを設定できる設定。
     -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Exchanger</title>
    <link rel ="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
    <link rel="stylesheet" href="CSS/style.css">
</head>
<body>
    <h1><i class="fa-solid fa-hand-holding-dollar"></i></h1>
    <h1>Exchange Rate Calculator</h1>
    <p>Choose the currency and the amounts to get the exchange</p>

    <div class = "container">
        <div class="currency">
            <select name="" id="currency-one">
                <option value="AED">AED</option>
                <option value="ARS">ARS</option>
                <option value="AUD">AUD</option>
                <option value="BGN">BGN</option>
                <option value="BRL">BRL</option>
                <option value="BSD">BSD</option>
                <option value="CAD">CAD</option>
                <option value="CHF">CHF</option>
                <option value="CLP">CLP</option>
                <option value="CNY">CNY</option>
                <option value="COP">COP</option>
                <option value="CZK">CZK</option>
                <option value="DKK">DKK</option>
                <option value="DOP">DOP</option>
                <option value="EGP">EGP</option>
                <option value="EUR">EUR</option>
                <option value="FJD">FJD</option>
                <option value="GBP">GBP</option>
                <option value="GTQ">GTQ</option>
                <option value="HKD">HKD</option>
                <option value="HRK">HRK</option>
                <option value="HUF">HUF</option>
                <option value="IDR">IDR</option>
                <option value="ILS">ILS</option>
                <option value="INR">INR</option>
                <option value="ISK">ISK</option>
                <option value="JPY">JPY</option>
                <option value="KRW">KRW</option>
                <option value="KZT">KZT</option>
                <option value="MXN">MXN</option>
                <option value="MYR">MYR</option>
                <option value="NOK">NOK</option>
                <option value="NZD">NZD</option>
                <option value="PAB">PAB</option>
                <option value="PEN">PEN</option>
                <option value="PHP">PHP</option>
                <option value="PKR">PKR</option>
                <option value="PLN">PLN</option>
                <option value="PYG">PYG</option>
                <option value="RON">RON</option>
                <option value="RUB">RUB</option>
                <option value="SAR">SAR</option>
                <option value="SEK">SEK</option>
                <option value="SGD">SGD</option>
                <option value="THB">THB</option>
                <option value="TRY">TRY</option>
                <option value="TWD">TWD</option>
                <option value="UAH">UAH</option>
                <option value="USD" selected>USD</option>
                <option value="UYU">UYU</option>
                <option value="VND">VND</option>
                <option value="ZAR">ZAR</option>
            </select>
            <input type="number" name="" id="amount-one" placeholder="0" value="1" />
        </div>


        <div class="swap-rate-container">
            <button class="btn" id="swap">
                Swap
            </button>
            <div class="rate" id="rate"></div>
        </div>


        <div class="currency">
            <select name="" id="currency-two">
                <option value="AED">AED</option>
                <option value="ARS">ARS</option>
                <option value="AUD">AUD</option>
                <option value="BGN">BGN</option>
                <option value="BRL">BRL</option>
                <option value="BSD">BSD</option>
                <option value="CAD">CAD</option>
                <option value="CHF">CHF</option>
                <option value="CLP">CLP</option>
                <option value="CNY">CNY</option>
                <option value="COP">COP</option>
                <option value="CZK">CZK</option>
                <option value="DKK">DKK</option>
                <option value="DOP">DOP</option>
                <option value="EGP">EGP</option>
                <option value="EUR" selected>EUR</option>
                <option value="FJD">FJD</option>
                <option value="GBP">GBP</option>
                <option value="GTQ">GTQ</option>
                <option value="HKD">HKD</option>
                <option value="HRK">HRK</option>
                <option value="HUF">HUF</option>
                <option value="IDR">IDR</option>
                <option value="ILS">ILS</option>
                <option value="INR">INR</option>
                <option value="ISK">ISK</option>
                <option value="JPY">JPY</option>
                <option value="KRW">KRW</option>
                <option value="KZT">KZT</option>
                <option value="MXN">MXN</option>
                <option value="MYR">MYR</option>
                <option value="NOK">NOK</option>
                <option value="NZD">NZD</option>
                <option value="PAB">PAB</option>
                <option value="PEN">PEN</option>
                <option value="PHP">PHP</option>
                <option value="PKR">PKR</option>
                <option value="PLN">PLN</option>
                <option value="PYG">PYG</option>
                <option value="RON">RON</option>
                <option value="RUB">RUB</option>
                <option value="SAR">SAR</option>
                <option value="SEK">SEK</option>
                <option value="SGD">SGD</option>
                <option value="THB">THB</option>
                <option value="TRY">TRY</option>
                <option value="TWD">TWD</option>
                <option value="UAH">UAH</option>
                <option value="USD">USD</option>
                <option value="UYU">UYU</option>
                <option value="VND">VND</option>
                <option value="ZAR">ZAR</option>
            </select>
            <input type="number" name="" id="amount-two" placeholder="0" />
        </div>
    </div>
   
    <script src="JS/script.js"></script>
</body>
</html>
```

#### 画面
![スクリーンショット 2022-06-04 1.45.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/6ca5cdf3-1cbb-fe8f-c66b-db90b50e91f0.png)
#### GIF
![Exchanger.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/126d6a3f-0ccb-bd03-7427-990160e11fd8.gif)

## 参考文献

◆非同期処理について

https://www.otwo.jp/blog/asynchronous-processing/

https://qiita.com/kiyodori/items/da434d169755cbb20447

https://qiita.com/codeship_tech/items/8858b0e0080051f0ce73

https://pikawaka.com/word/ajax

◆XMLHttpRequest（ブラウザとサーバ間でのHTTPのやりとりについて）

https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest

◆fetch APIについて

https://javascript.keicode.com/newjs/fetch.php

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

https://kde.hateblo.jp/entry/2018/10/22/010811

https://into-the-program.com/javascript-get-json-data-with-fetch/

◆プロミスについて

https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Using_promises

https://qiita.com/cheez921/items/41b744e4e002b966391a

◆コールバック関数とは

https://sbfl.net/blog/2019/02/08/javascript-callback-func/