6日目のゴールと今日やること
6日目のテーマは
「Datamuse API アプリを“整理された設計”に進化させ、fetch / async‑await / エラーハンドリングを“アプリ全体の仕組み”として理解する」
ことです。
ここまでであなたは、
検索・サジェスト・履歴・お気に入り・localStorage 保存まで実装してきました。
6日目は、これらを 「読みやすく・直しやすく・拡張しやすいコード」 に整理していきます。
今日の内容は、アプリ開発の中級者が必ず通る「設計の壁」を越えるためのものです。
状態管理(state)をアプリの中心に置く
なぜ state が必要なのか
昨日までのコードは、
履歴・お気に入り・ローディング状態などがバラバラの変数で存在していました。
これをひとつの state にまとめると、
- どこに何があるか迷わない
- UI 更新がしやすい
- 保存(localStorage)と連動しやすい
- デバッグがしやすい
というメリットがあります。
state の基本形
const state = {
isLoading: false,
history: [],
favorites: [],
suggestions: []
};
JavaScript状態を更新する関数
function updateState(updates) {
Object.assign(state, updates);
}
JavaScriptこれにより、updateState({ isLoading: true })
のように、どこからでも状態を更新できます。
fetch を「共通関数」にまとめて再利用する
なぜ共通化が必要なのか
Datamuse アプリでは、
- 本検索
- サジェスト
- 複数モード検索
- 履歴からの再検索
- お気に入りからの再検索
など、fetch を使う場面が多いです。
そこで、
fetch のエラーハンドリングを共通化した関数
を作ります。
共通の JSON リクエスト関数(重要)
async function requestJson(url) {
try {
const response = await fetch(url);
if (!response.ok) {
if (response.status === 429) {
throw new Error("リクエストが多すぎます。少し待ってから再試行してください。");
}
if (response.status >= 500) {
throw new Error("サーバー側でエラーが発生しています。時間をおいて再試行してください。");
}
throw new Error(`HTTPエラー(${response.status})`);
}
const data = await response.json();
return data;
} catch (error) {
throw new Error(error.message);
}
}
JavaScript深掘りポイント
この関数は、
- fetch の失敗
- HTTP エラー
- JSON パースエラー
をすべて Error として上に投げる 役割を持っています。
これにより、
上位の関数は「成功したか・失敗したか」だけを扱えばよくなります。
Datamuse 専用の検索関数を作る
Datamuse の仕様チェックをここに集約する
async function searchDatamuse(word, mode) {
const url = `https://api.datamuse.com/words?${mode}=${encodeURIComponent(word)}`;
const data = await requestJson(url);
if (!Array.isArray(data)) {
throw new Error("予期しない形式のデータが返されました。");
}
if (data.length === 0) {
throw new Error("該当する単語が見つかりませんでした。");
}
const sorted = [...data].sort((a, b) => (b.score || 0) - (a.score || 0));
return sorted;
}
JavaScript深掘りポイント
searchDatamuse は
「Datamuse API の仕様を知っている唯一の関数」
です。
UI 側は Datamuse の細かい仕様を知らなくてよくなり、
コードが読みやすくなります。
UI 側の関数を「ストーリーとして読める」形にする
fetchWords の完成形(6日目版)
async function fetchWords() {
const word = wordInput.value.trim();
const mode = modeSelect.value;
if (!word) {
statusDiv.textContent = "単語を入力してください。";
resultDiv.textContent = "";
return;
}
const modeLabel = getModeLabel(mode);
startLoading(`${modeLabel}を取得中です…`);
resultDiv.textContent = "";
try {
const words = await searchDatamuse(word, mode);
statusDiv.textContent = `${modeLabel}の取得に成功しました。`;
renderWords(words, modeLabel);
addHistory(word, mode);
} catch (error) {
statusDiv.textContent = `検索中にエラーが発生しました:${error.message}`;
console.error(error);
} finally {
endLoading();
}
}
JavaScript深掘りポイント
この関数は、
「翻訳の流れをそのまま読める」
という設計になっています。
- 入力チェック
- ローディング開始
- Datamuse に検索
- 成功時の表示
- 履歴追加
- 失敗時のメッセージ
- ローディング終了
fetch の細かい処理はsearchDatamuse と requestJson に隠れているため、
とても読みやすくなっています。
複数モード検索を Promise.all で同時に行う
複数モード検索の関数
async function searchMultipleModes(word) {
const promises = [
searchDatamuse(word, "ml"),
searchDatamuse(word, "rel_trg")
];
const [similar, related] = await Promise.all(promises);
return { similar, related };
}
JavaScript深掘りポイント
Promise.all を使うと、
- 並列で API を叩ける
- 全部終わるまで待てる
- 結果をまとめて扱える
というメリットがあります。
ローディング表示を「複数リクエスト」に対応させる
state と連動させる
function startLoading(message) {
updateState({ isLoading: true });
statusDiv.textContent = message || "処理中です…";
searchButton.disabled = true;
multiButton.disabled = true;
}
function endLoading() {
updateState({ isLoading: false });
searchButton.disabled = false;
multiButton.disabled = false;
}
JavaScript深掘りポイント
複数モード検索でも、
単一検索でも、
ローディング表示が一貫して動く ようになります。
エラーハンドリングを「原因別」に整理する
requestJson の中で原因別に分岐
- 429 → リクエスト過多
- 500 番台 → サーバー側の問題
- その他 → 一般的な HTTP エラー
ユーザーにとっては、
「自分が悪いのか、サーバーが悪いのか」
がわかるだけでストレスが減ります。
6日目のまとめ
今日やったことを整理すると、こうなります。
- fetch を requestJson に共通化
- Datamuse 専用の searchDatamuse を作成
- UI 側の fetchWords を「読みやすい流れ」に整理
- Promise.all で複数モード検索を実装
- ローディング表示を state と連動
- エラーハンドリングを原因別に整理
どれも新しい文法ではなく、
「fetch / async‑await / エラーハンドリングを“設計として扱う”」
という話です。
今日いちばん深く理解してほしいこと
6日目の本質は、
「コードは“動けばいい”から、“読めて直せて拡張できる”に育てていくもの」
ということです。
Datamuse アプリは、
fetch → async/await → try-catch → state → UI
という“型”の上に成り立っています。
7日目では、このアプリを
中級編の完成形としてまとめる
回に入ります。
あなたのアプリが「本当に使えるツール」になる瞬間です。


