6日目のゴールと今日やること
6日目のテーマは
「Nager.Date API 祝日アプリを“読みやすく・直しやすく・拡張しやすい設計”に進化させる」
ことです。
ここまでであなたは、
- 年・国を指定して祝日取得
- ローディング表示
- エラーハンドリング
- 前年・翌年・今年ボタン
- お気に入り機能
- localStorage 保存
- 複数国比較(Promise.all)
といった、API アプリの本質をすでに体験しています。
6日目は、これらを 「設計として整理する」 回です。
つまり、
fetch / async‑await / エラーハンドリングを“アプリ全体の型”として扱えるようにする
ことが目的です。
状態管理(state)をアプリの中心に置く
なぜ state を中心にするのか
昨日までのコードでは、
祝日一覧・お気に入り・ローディング状態などが
バラバラの変数として存在していました。
これをひとつの state にまとめると、
- どこに何があるか迷わない
- UI 更新がしやすい
- 保存(localStorage)と連動しやすい
- デバッグがしやすい
というメリットがあります。
state の基本形
const state = {
isLoading: false,
holidays: [],
favorites: [],
comparison: []
};
JavaScript状態を更新する関数
function updateState(updates) {
Object.assign(state, updates);
}
JavaScriptこの関数があるだけで、
アプリ全体のコードがスッキリします。
fetch を「共通関数」にまとめて再利用する
なぜ共通化が必要なのか
祝日アプリでは、
- 単一国の祝日取得
- 複数国比較
- お気に入りからの再取得
など、fetch を使う場面が多いです。
そこで、
fetch のエラーハンドリングを共通化した関数
を作ります。
共通 fetch 関数(重要)
async function requestJson(url) {
try {
const response = await fetch(url);
if (!response.ok) {
if (response.status === 404) {
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 として上に投げる 役割を持っています。
これにより、
上位の関数は「何をしたいか」だけに集中できます。
Nager.Date 専用の関数を作る
祝日取得を「読みやすい関数」にする
async function fetchPublicHolidays(year, countryCode) {
const url = `https://date.nager.at/api/v3/PublicHolidays/${year}/${countryCode}`;
const data = await requestJson(url);
if (!Array.isArray(data)) {
throw new Error("予期しない形式のデータが返されました。");
}
if (data.length === 0) {
throw new Error("祝日が見つかりませんでした。");
}
return data;
}
JavaScript深掘りポイント
fetchPublicHolidays は
「Nager.Date API の仕様を知っている唯一の関数」
です。
UI 側は API の細かい仕様を知らなくてよくなり、
コードが読みやすくなります。
UI 側の fetchHolidays を“ストーリーとして読める”形にする
6日目版 fetchHolidays(完成形)
async function fetchHolidays() {
const rawYear = yearInput.value.trim();
const countryCode = countrySelect.value;
const parsed = parseYear(rawYear);
if (!parsed.ok) {
statusDiv.textContent = parsed.message;
resultDiv.textContent = "";
return;
}
const year = parsed.value;
setLoading(true, `${year}年の祝日を取得中です…`);
resultDiv.textContent = "";
try {
const holidays = await fetchPublicHolidays(year, countryCode);
updateState({ holidays });
statusDiv.textContent = "祝日の取得に成功しました。";
renderHolidays(holidays);
} catch (error) {
statusDiv.textContent = `取得中にエラーが発生しました:${error.message}`;
console.error(error);
} finally {
setLoading(false);
}
}
JavaScript深掘りポイント
この関数は、
「祝日取得の流れをそのまま読める」
という設計になっています。
- 入力チェック
- ローディング開始
- fetchPublicHolidays で祝日取得
- 成功時の表示
- 失敗時のメッセージ
- ローディング終了
fetch の細かい処理はfetchPublicHolidays と requestJson に隠れているため、
とても読みやすくなっています。
複数国比較を Promise.all で整理する
複数国比較の関数
async function fetchMultipleCountries(year, countries) {
const promises = countries.map((code) =>
fetchPublicHolidays(year, code)
);
const results = await Promise.all(promises);
return results;
}
JavaScript深掘りポイント
Promise.all を使うと、
- 並列で API を叩ける
- 全部終わるまで待てる
- 結果をまとめて扱える
というメリットがあります。
ローディング表示を「状態」として扱う
state と連動させる
function setLoading(isLoading, message) {
updateState({ isLoading });
if (isLoading) {
statusDiv.textContent = message || "処理中です…";
}
fetchButton.disabled = isLoading;
compareButton.disabled = isLoading;
thisYearButton.disabled = isLoading;
prevYearButton.disabled = isLoading;
nextYearButton.disabled = isLoading;
}
JavaScript深掘りポイント
複数国比較でも、
単一国の取得でも、
ローディング表示が一貫して動く ようになります。
エラーハンドリングを「原因別」に整理する
どこで何を扱うか
- 入力エラー → parseYear
- HTTP エラー → requestJson
- データ形式エラー → fetchPublicHolidays
- 該当なし → fetchPublicHolidays
- ネットワークエラー → catch
このように、
エラーの責任を関数ごとに分ける
ことで、コードが読みやすくなります。
6日目のまとめ
今日あなたがやったことを整理すると、こうなります。
- fetch を requestJson に共通化
- Nager.Date 専用の fetchPublicHolidays を作成
- UI 側の fetchHolidays を「読みやすい流れ」に整理
- Promise.all で複数国比較を整理
- ローディング表示を state と連動
- エラーハンドリングを原因別に整理
- 状態管理(state)をアプリの中心に置いた
どれも新しい文法ではなく、
「fetch / async‑await / エラーハンドリングを“設計として扱う”」
という話です。
今日いちばん深く理解してほしいこと
6日目の本質は、
「コードは“動けばいい”から、“読めて直せて拡張できる”に育てていくもの」
ということです。
祝日アプリは、
fetch → async/await → try-catch → state → UI
という“型”の上に成り立っています。
7日目では、このアプリを
中級編の完成形としてまとめる
回に入ります。
あなたのアプリが「本当に使えるツール」になる瞬間です。


