【JavaScript】非同期通信入門


#目標

今回は、ボタンを押すとjsonで取得したリストを10件ずつ表示していく機能を非同期処理で実装していきます。

はじめにXMLHttpRequestを使用した非同期処理の方法を見ていき、
そのあとでasync / awaitを利用した非同期処理の方法を見ていきます。

#jsonデータ

今回使用させていただくデータはjsonplaceholderのuser情報です。

https://jsonplaceholder.typicode.com/

#完成コード

要所ごとに詳細に説明していきます。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>非同期処理でユーザーのリストを追加してみよう</title>
</head>
<body>

  <ol id="lists"></ol>
  <button id="btn">もっと見る</button>

</body>
<script src="index.js"></script>
</html>
```

```js

let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/users', true)
xhr.responseType = 'json'
xhr.send(null)
xhr.onload = function(e) {
  if (xhr.readyState == 4) {
    if (xhr.status == 200 ) {

      let btn = document.getElementById('btn');
      let users = xhr.response;
      let lists = document.getElementById('lists');

      btn.addEventListener('click', function() {
        users.forEach(function (user) {
          let li = document.createElement('li');
          li.innerText = user.name
          lists.appendChild(li)
        });
      });

    }
  }
}

```

基本このフォーマットなので、定型文として覚えて大丈夫です。

各処理が実際に何をしているかフローを見ていきましょう。

1. new演算子を利用してオブジェクトを生成します。
2. open( )メソッドを利用して、`メソッド`、`URL`、`非同期処理の有無`を引数に渡します。第3引数を`false`にすると、同期処理になります。
3. responseTypeで`json`を指定します。
4. send( )メソッドでAPIを呼び出して通信を開始します。`null`は送るものがないことを意味します。open( )のメソッドが`POST`の場合、send( )に処理したいデータを格納できます。
5. リクエストに対して返ってきたレスポンスの処理を`xhr.onload=function(e){}`に格納します。
6. `readyState`は現在の通信状況を示しています。`4`は通信完了という意味になります。
7. `status`で`200`は正常に通信出来ていることを示しています。もしファイルが存在しなかったりすると404が返ってきます。
8. `xhr.response`でレスポンスで返ってきたデータをコンソールに表示します。 

```js
let xhr = new XMLHttpRequest();
// 今回はデータを取得するだけなのでGETを渡します。
// 非同期処理なのでtrueを渡します。
xhr.open('GET', 'https://jsonplaceholder.typicode.com/users', true)
xhr.responseType = 'json'
xhr.send(null)
xhr.onload = function(e) {
  if (xhr.readyState == 4) {
    if (xhr.status == 200 ) {
      console.log(xhr.response) // データが返る
    }
  }
}
```
イベント処理です。
今回ここで行われている処理の説明は割愛させていただきます。

```js

  // 省略  
      let btn = document.getElementById('btn'); 
      let lists = document.getElementById('lists');
      let users = xhr.response;  // 変数usersにデータを代入

      btn.addEventListener('click', function() {
        users.forEach(function (user) { // 新しく生成したliにuser情報を入れます
          let li = document.createElement('li');
          li.innerText = user.name 
          lists.appendChild(li)
        });
      });
  // 省略
```

#async await

今度はasync / awaitを使って同じ処理を書き換えていきます。

```js
let lists = document.getElementById('lists');
let btn = document.getElementById('btn');

btn.addEventListener('click', async function () {
  // URLを格納します。fetchを使うと外部との連携ができるようにになります。
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  // レスポンスで返ってきたデータをjson形式で格納します。
  const users = await res.json();
  // forEach文で新しく生成したli要素にuser情報をいれます。
  users.forEach(function (user) {      
    const list = document.createElement('list');
    list.innerText = user.name
    lists.appendChild(list);
  });
})

```

これで書き換え終了です。無事に表示できたましたでしょうか。
追加で初回のロードした時に既に10件表表示されている実装も行いましょう。
また記述が上々になったり分割できる所が見受けられるのでリファクタリングも行いましょう。

```js
let lists = document.getElementById('lists');
let btn = document.getElementById('btn');

async function getUsers() {
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  const users = await res.json();
  return users
}
async function listUsers() {
  const users = await getUsers();
  users.forEach(addList);
}

function addList(user) {      
  const list = document.createElement('list');
  list.innerText = user.name
  list.style.display = 'block'
  lists.appendChild(list);
}

window.addEventListener('load', listUsers)
btn.addEventListener('click', listUsers)

```


以上