JavaScriptのきほん(16)「外部データを取得しよう(2)async/awaitで書き換えよう」

スポンサーリンク
JavaScript

前回は、fetch()と.then()を使って外部のToDoデータを画面に表示した。
.then()を続ける書き方は、処理が増えると読みにくくなっていく。今回はasync/awaitという書き方に整理しなおし、取得する件数を選べる機能と、データを取得しなおすボタンを加えてみよう。

1. async/awaitとは

async/awaitは、Promiseを使った処理を、上から下へ順に読める形で書くための仕組みである。

  • async:関数の前に付けると、その関数の中でawaitが使えるようになる
  • await:Promiseの結果が届くまで、その場で待つ

前回の.then()をつないだ処理は、awaitを使うと次のように書き換えられる。

const response = await fetch(API_URL);
const todos = await response.json();

変数に結果を代入していくだけなので、処理の流れが追いやすい。

2. index.html

前回のindex.htmlの<h1>の下に、件数を選ぶ選択欄と再読み込みボタンを追加しよう。

<label>件数:
  <select id="limit-select">
    <option value="5">5件</option>
    <option value="10">10件</option>
    <option value="20">20件</option>
  </select>
</label>
<button id="reload-button">再読み込み</button>

3. script.js

script.jsの中身を、次のコードに置き換えよう。

const BASE_URL = 'https://jsonplaceholder.typicode.com/todos';
const list = document.getElementById('todo-list');
const message = document.getElementById('message');
const select = document.getElementById('limit-select');
const button = document.getElementById('reload-button');

async function loadTodos() {
  message.textContent = '読み込み中...';
  list.innerHTML = '';
  button.disabled = true;
  select.disabled = true;

  const response = await fetch(`${BASE_URL}?_limit=${select.value}`);
  const todos = await response.json();

  todos.forEach((todo) => {
    const li = document.createElement('li');
    li.textContent = (todo.completed ? '✅ ' : '⬜ ') + todo.title;
    list.appendChild(li);
  });

  message.textContent = `${todos.length}件取得した`;
  button.disabled = false;
  select.disabled = false;
}

select.addEventListener('change', loadTodos);
button.addEventListener('click', loadTodos);
loadTodos();

4. コードの解説

処理全体をasync function loadTodos()にまとめた。選択欄を変えたときも、ボタンを押したときも、ページを開いたときも、同じ関数を呼ぶだけで取得できる。.then()の版では、取得のたびに同じ処理を書き写す必要があったが、関数にしておけばその手間がない。

取得先のURLは、テンプレートリテラルで組み立てている。select.valueは選択中のvalueの値で、文字列として届く。_limit=5のように件数がURLに入るため、選択を変えるだけで取得件数が切り替わる。

awaitの行では、結果が届くまで次の行に進まない。待っている間もブラウザは固まらず、画面には先に「読み込み中…」が表示されている。
また、取得中はbutton.disabled = trueとselect.disabled = trueでボタンと選択欄を無効にし、終わったら元に戻している。連打や素早い切り替えによる二重取得を防ぐための工夫である。

5. 動作確認とまとめ

ブラウザで開き、件数を5件・10件・20件と切り替えてみよう。
選ぶたびにリストが入れ替われば成功である。

今回のポイントは次の3点である。

  • asyncを付けた関数の中では、awaitで結果を待てる
  • 処理を関数にまとめると、複数のきっかけから呼び出せる
  • 件数のような変化する値は、テンプレートリテラルでURLに組み込める

ただし、このコードは通信が必ず成功する前提のままである。ネットワークを切断してから操作すると、「読み込み中…」のまま止まり、ボタンも選択欄も操作できなくなってしまう。
次回は、通信に失敗した場合の備えを加えていこう。

コメント

タイトルとURLをコピーしました