JavaScript の Fetch API を用いた HTTPリクエストで簡略な時間的制約を設ける

タイトル通りの内容の、ちょっとしたメモです。

## 今回の内容
[Fetch API](https://developer.mozilla.org/ja/docs/Web/API/Fetch_API) などを使って HTTPリクエストを実行する際に、例えば「1度 HTTPリクエストを送ったらその後 5秒間は HTTPリクエストを送る処理を実行しないようにする」というような、時間的制約をかける話です。
指定の時間が経過するまでは HTTPリクエストを実行しようとしてもその処理をブロックするようなフラグを立てておく、という形で実現してみます。

## 時間的な制約をかける
「処理をブロックするようなフラグ」という話を書きましたが、このフラグがオンになった後に、一定の時間が経過したらフラグがオフになる、というような処理を実装します。
具体的には、「JavaScript で sleep処理を実現する方法」というような方向性で情報を探した時によくでてくる、「async/await を使った sleep処理」を使います。

●非同期関数 - JavaScript | MDN
　https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function
●awaitできるsetTimeoutを1行で書く方法 - Qiita
　https://qiita.com/suin/items/99aa8641d06b5f819656

ちなみに sleep処理を実現する部分のメインの処理は、以下のような形になります。

```javascript
await new Promise(resolve => setTimeout(resolve, 3000));
```

## Fetch API による HTTPリクエスト
まずは、Fetch API でシンプルに HTTPリクエストを実行する処理について、[HTTPBin（httpbin.org）](https://httpbin.org/) を利用したものを準備します。
なお、HTTPBin を使って実行できる処理はいくつか種類がありますが、今回は https://httpbin.org/json へのアクセスによる JSON の取得を行ってみます。

```html
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Fetch API による HTTPリクエスト</title>
</head>

<body>
  <h1>Fetch API による HTTPリクエスト</h1>
  <button id="button01">HTTPリクエストを実行</button>

  <script>
    let waitFlag = false;
    const url = "https://httpbin.org/json";

    const button01 = document.getElementById("button01");
    button01.addEventListener("click", httpGet, false);

    async function httpGet() {
      const res = await fetch(url);
      let json;
      try {
        if (res.ok) {
          json = await res.json();
        } else {
          throw new Error(res.status);
        }
      } catch (e) {
        console.error(e);
      }
      console.log(json);
    }
  </script>
</body>

</html>
```

上記をブラウザで開いてページ上のボタンを押下すると、HTTPリクエストで取得できた JSON の情報が、ブラウザのコンソールに出力されるのが確認できるかと思います。

## 時間的な制約をかけた HTTPリクエスト
次に、上記の HTTPリクエストを行ったものに、以下の処理を利用して時間的な制約をつけます。

```javascript
(async () => {
  console.log("待ち開始");
  await new Promise(resolve => setTimeout(resolve, 5000));
  console.log("待ち終了");
  waitFlag = false;
})();
```

以下に、処理を行うためのソース全体を掲載します。

```html
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>HTTPリクエストの連続実行に時間的な制約をかける</title>
</head>

<body>
  <h1>HTTPリクエストの連続実行に時間的な制約をかける</h1>
  <button id="button01">HTTPリクエストを実行</button>

  <script>
    let waitFlag = false;
    const url = "https://httpbin.org/json";

    const button01 = document.getElementById("button01");
    button01.addEventListener("click", httpGet, false);

    async function httpGet() {
      if (!waitFlag) {
        waitFlag = true;
        const res = await fetch(url);
        let json;
        try {
          if (res.ok) {
            json = await res.json();
          } else {
            throw new Error(res.status);
          }
        } catch (e) {
          console.error(e);
        }
        console.log(json);

        (async () => {
          console.log("待ち開始");
          await new Promise(resolve => setTimeout(resolve, 5000));
          console.log("待ち終了");
          waitFlag = false;
        })();
      }
    }
  </script>
</body>

</html>
```

上記をブラウザで開いてページ上のボタンを押下すると、1回目は先ほどの時間的な制約がないものと同様の動きをするのが確認できるかと思います。
さらに、1回目のボタン押下の直後から 5秒経過するまでの間は、再度ボタンを押下しても HTTPリクエストが実行されない（取得した JSON の出力が行われない）のも確認できるかと思います。

## 【追記】 同時に処理できる数で制限する
この記事を公開した後、「非同期処理を同時に実行できる数を制限する、みたいな話を最近見た気がする」と思って、かつ、それを見返したくなることがあるかも、と思ったのでここへ追記する形でメモ。

●Javascriptで同時に非同期処理を行う | DevelopersIO
　https://dev.classmethod.jp/articles/resolve-promise-at-same-time/