JavaScript | 1 日 120 分 × 7 日アプリ学習:API通信アプリ(Datamuse API)

APP JavaScript
スポンサーリンク

1日目のゴールと今日やること

Datamuse API 中級編 1 日目のテーマは
「単語を入力すると、関連する単語や類義語を API から取得して表示するミニアプリを作る」
ことです。

キーワードはこの 3 つです。

  • fetch
  • Promise / async-await
  • エラーハンドリング

実装としては、まずこのレベルを目指します。

  • テキストボックスに英単語を入力
  • 「検索」ボタンを押す
  • Datamuse API から関連語(似た意味の単語など)を取得
  • 取得中は「読み込み中…」を表示
  • 成功したら単語一覧を表示
  • 失敗したらエラーメッセージを表示

「ニュース」や「天気」と違って、
今日は「単語遊び」がテーマです。
でも、使う技術はまったく同じ——fetch・async/await・エラーハンドリングです。


Datamuse API のざっくり概要

Datamuse API って何をしてくれるの?

Datamuse API は、
「単語に関するいろいろな情報を返してくれる無料の API」 です。

例えば:

  • 類義語(似た意味の単語)
  • 連想語(その単語から連想される単語)
  • 韻を踏む単語
  • 前方一致・後方一致の単語

などを簡単に取得できます。

今日使うのは、まず一番シンプルなエンドポイントです。

https://api.datamuse.com/words?ml=word

ml は「means like(〜のような意味)」の略で、
ml=happy とすると「happy に意味が近い単語」が返ってきます。


今日作るミニアプリのイメージ

画面構成

まずは、超シンプルな UI を考えます。

  • 単語入力欄(英単語)
  • 「関連語を検索」ボタン
  • ステータス表示(読み込み中・成功・エラー)
  • 結果表示(関連語の一覧)

HTML のイメージはこんな感じです。

<input id="wordInput" placeholder="英単語を入力 (例: happy)" />
<button id="searchButton">関連語を検索</button>

<div id="status"></div>
<div id="result"></div>

status は「ローディングやエラー表示」用、
result は「関連語一覧の表示」用です。


fetch を「サーバーにお願いしに行く関数」として理解する

fetch の基本形

fetch は、
「この URL にアクセスして、結果をちょうだい」
とブラウザに頼む関数です。

一番シンプルな形はこうです。

fetch("https://api.datamuse.com/words?ml=happy")
  .then((response) => {
    console.log("レスポンスが返ってきた", response);
  })
  .catch((error) => {
    console.error("通信に失敗した", error);
  });
JavaScript

ここで大事なのは、

  • fetch は「すぐに結果」ではなく「Promise(あとで結果がわかる箱)」を返す
  • then は「成功したときにやること」
  • catch は「失敗したときにやること」

ということです。


Promise と async/await をかみ砕いて理解する

Promise は「未来の結果の箱」

fetch を呼ぶと、
「今はまだ結果がないけど、終わったら教えるね」という
Promise が返ってきます。

const promise = fetch(url);
// promise は「いつか結果が入る箱」
JavaScript

then で「終わったらこれをしてね」と予約します。

promise.then((response) => {
  console.log("終わったよ", response);
});
JavaScript

async/await は「同期っぽく書ける魔法の文法」

Promise を then でつなぐと、
ネストが深くなりがちなので、
よく使われるのが async/await です。

async function getData() {
  try {
    const response = await fetch(url);
    console.log("レスポンス", response);
  } catch (error) {
    console.error("エラー", error);
  }
}
JavaScript
  • await は「この Promise が終わるまでここで待つ」
  • async は「この関数の中で await を使いますよ」という宣言

この 2 つはセットで使います。


Datamuse API のレスポンス形式を知る

どんな JSON が返ってくるのか

例えば、https://api.datamuse.com/words?ml=happy にアクセスすると、
ざっくりこんな JSON が返ってきます。

[
  { "word": "glad", "score": 1234 },
  { "word": "joyful", "score": 1100 },
  { "word": "cheerful", "score": 980 }
]

ポイントは:

  • 配列([])で返ってくる
  • 各要素はオブジェクト({}
  • word に単語、score に関連度のような数値

つまり、
「配列をループして word を取り出して表示する」
という構造になります。


イベントの準備と「中心となる async 関数」

DOM 要素を取得する

まずは JavaScript で HTML 要素を取ってきます。

const wordInput = document.getElementById("wordInput");
const searchButton = document.getElementById("searchButton");
const statusDiv = document.getElementById("status");
const resultDiv = document.getElementById("result");
JavaScript

ボタンにクリックイベントを付ける

searchButton.addEventListener("click", () => {
  const word = wordInput.value.trim();

  if (!word) {
    statusDiv.textContent = "単語を入力してください。";
    resultDiv.textContent = "";
    return;
  }

  fetchRelatedWords(word);
});
JavaScript

ここまでは「きっかけ作り」です。
本番は fetchRelatedWords の中身です。


ローディング表示を入れて「ちゃんと待っている」ことを伝える

通信前にローディング状態にする

ユーザーは「押したのに何も起きない」と不安になります。
なので、通信前に必ず「今取りに行ってますよ」と伝えます。

async function fetchRelatedWords(word) {
  statusDiv.textContent = "関連語を取得中です…";
  resultDiv.textContent = "";
  searchButton.disabled = true;

  try {
    const url = `https://api.datamuse.com/words?ml=${encodeURIComponent(word)}`;
    const response = await fetch(url);

    // ここからレスポンスのチェック
  } catch (error) {
    // 通信レベルのエラー
  } finally {
    // 最後に必ずボタンを戻す
  }
}
JavaScript

ここで重要なのは、

  • ローディング表示は fetch の前に出す
  • ボタンを無効化して「連打による多重起動」を防ぐ

という 2 点です。


エラーハンドリングの 2 段階を意識する(Datamuse 版)

NewsAPI や WeatherAPI と違って、
Datamuse は「status: ‘error’」のようなフィールドを返しません。
その代わり、次の 2 段階を意識します。

段階 1:fetch 自体の失敗(ネットワークエラー)

try {
  const response = await fetch(url);
} catch (error) {
  statusDiv.textContent = "通信に失敗しました。ネットワークを確認してください。";
  console.error(error);
  searchButton.disabled = false;
  return;
}
JavaScript

ここでの失敗は、
「サーバーにたどり着けなかった」などのレベルです。

段階 2:HTTP ステータスコードのチェック

Datamuse は基本的に 200 を返しますが、
一般的なパターンとして response.ok をチェックする癖をつけます。

const response = await fetch(url);

if (!response.ok) {
  statusDiv.textContent = `サーバーエラーが発生しました。(${response.status})`;
  searchButton.disabled = false;
  return;
}
JavaScript

response.ok はステータスコードが 200〜299 のとき true になります。


成功時の関連語一覧表示を作る

JSON をパースして配列を扱う

const data = await response.json();
JavaScript

data は配列です。
中身が空かどうかをチェックします。

if (!Array.isArray(data) || data.length === 0) {
  statusDiv.textContent = "関連する単語が見つかりませんでした。";
  resultDiv.textContent = "";
  searchButton.disabled = false;
  return;
}
JavaScript

単語一覧を HTML に変換する

function renderWords(data) {
  let html = "<h3>関連する単語</h3>";

  data.forEach((item) => {
    const word = item.word;
    const score = item.score;
    html += `<p>${word}(スコア: ${score})</p>`;
  });

  resultDiv.innerHTML = html;
}
JavaScript

fetchRelatedWords の中で呼び出します。

statusDiv.textContent = "関連語の取得に成功しました。";
renderWords(data);
JavaScript

通信失敗時の分岐を「ユーザー目線」で設計する

失敗パターンをざっくり分ける

1 日目で意識してほしいのは、
「全部まとめて“エラーです”で終わらせない」ことです。

Datamuse の場合、ざっくりこう分けられます。

  • ネットワークエラー(オフラインなど)
  • HTTP エラー(500 番台など)
  • データは返ってきたが、配列が空(該当なし)

それぞれメッセージを変えます。

  • 「通信に失敗しました。ネットワークを確認してください。」
  • 「サーバーエラーが発生しました。(ステータスコード)」
  • 「関連する単語が見つかりませんでした。」

これだけで、ユーザーの安心感がかなり変わります。


1日目の完成コード(重要部分をまとめて)

const wordInput = document.getElementById("wordInput");
const searchButton = document.getElementById("searchButton");
const statusDiv = document.getElementById("status");
const resultDiv = document.getElementById("result");

function renderWords(data) {
  let html = "<h3>関連する単語</h3>";

  data.forEach((item) => {
    const word = item.word;
    const score = item.score;
    html += `<p>${word}(スコア: ${score})</p>`;
  });

  resultDiv.innerHTML = html;
}

async function fetchRelatedWords(word) {
  statusDiv.textContent = "関連語を取得中です…";
  resultDiv.textContent = "";
  searchButton.disabled = true;

  try {
    const url = `https://api.datamuse.com/words?ml=${encodeURIComponent(word)}`;
    const response = await fetch(url);

    if (!response.ok) {
      statusDiv.textContent = `サーバーエラーが発生しました。(${response.status})`;
      return;
    }

    const data = await response.json();

    if (!Array.isArray(data) || data.length === 0) {
      statusDiv.textContent = "関連する単語が見つかりませんでした。";
      resultDiv.textContent = "";
      return;
    }

    statusDiv.textContent = "関連語の取得に成功しました。";
    renderWords(data);

  } catch (error) {
    statusDiv.textContent = "通信に失敗しました。ネットワークを確認してください。";
    console.error(error);

  } finally {
    searchButton.disabled = false;
  }
}

searchButton.addEventListener("click", () => {
  const word = wordInput.value.trim();

  if (!word) {
    statusDiv.textContent = "単語を入力してください。";
    resultDiv.textContent = "";
    return;
  }

  fetchRelatedWords(word);
});
JavaScript

今日いちばん深く理解してほしいこと

1 日目で本当に押さえてほしいのは、この 3 つです。

  • fetch は「Promise を返す非同期処理」である
  • async/await で「同期っぽく書きつつ、try-catch でエラーを扱う」
  • エラーハンドリングは「通信エラー」「HTTP エラー」「該当なし」を分けて考える

そしてもうひとつ大事なのは、
「API が返す JSON の形をちゃんと理解してからコードを書く」
という姿勢です。

Datamuse は「配列で返す」「word と score を持つ」
NewsAPI は「オブジェクトで返す」「articles を持つ」
WeatherAPI は「location や current を持つ」

API ごとに形は違うけれど、
fetch・async/await・エラーハンドリングの“型”は同じです。

ここまでできたあなたは、
もう「API を触ってみている人」ではなく、
“API のレスポンス構造を理解して設計できる人” の入り口に立っています。

2 日目以降は、この Datamuse アプリに

  • 検索モードの切り替え(類義語 / 連想語 / 韻を踏む単語)
  • ローディング表示の改善
  • 簡単なバリデーションや UI 調整

などを足して、
「言葉遊びができる便利ツール」に育てていきましょう。

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