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

APP JavaScript
スポンサーリンク

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

1日目のテーマは
「Nager.Date API を使って “今年の祝日一覧アプリ” を作りながら、fetch / async‑await / エラーハンドリングの基本パターンを体で覚える」
ことです。

Nager.Date API は「国ごとの祝日情報」を返してくれる無料の API です。
日本(JP)、アメリカ(US)、ドイツ(DE)など、国コードを指定して祝日一覧を取得できます。

今日は、次の流れを一気に体験します。

  • 国と年を選ぶ
  • 「祝日を取得」ボタンを押す
  • Nager.Date API から祝日一覧を取得
  • ローディング表示を出す
  • 通信失敗時にわかりやすいメッセージを出す

ここで使う技術が、まさに

  • fetch
  • Promise / async‑await
  • エラーハンドリング(try / catch)

です。


Nager.Date API をざっくり理解する

どんな API なのか

Nager.Date API の祝日エンドポイントは、こんな形です。

https://date.nager.at/api/v3/PublicHolidays/{year}/{countryCode}

例えば:

  • 2025年の日本の祝日
    https://date.nager.at/api/v3/PublicHolidays/2025/JP
  • 2024年のアメリカの祝日
    https://date.nager.at/api/v3/PublicHolidays/2024/US

返ってくるのは JSON(JavaScript で扱いやすいデータ形式)で、
1件ずつの祝日がオブジェクトとして入った配列です。

ざっくりこんなイメージです。

[
  {
    "date": "2025-01-01",
    "localName": "元日",
    "name": "New Year's Day",
    "countryCode": "JP"
  },
  ...
]

この「配列の JSON」を fetch で取りに行って、画面に表示していきます。


fetch をかみ砕いて理解する

fetch は「ブラウザに API へ行ってきて」と頼む関数

JavaScript の fetch は、
「この URL にアクセスして、結果を持ってきて」
とブラウザにお願いする関数です。

例:

fetch("https://date.nager.at/api/v3/PublicHolidays/2025/JP");
JavaScript

ただし、fetch はすぐに結果そのものを返しません。
返してくるのは Promise(未来の結果が入る箱) です。

「今はまだ結果がないけど、そのうち入るよ」という感じです。


async / await で「待つ」コードを書く

then だらけになるのを避ける

Promise は then でつなげて書くこともできますが、
ネストが深くなって読みづらくなりがちです。

そこで使うのが async / await です。

async function getHolidays() {
  const response = await fetch("https://date.nager.at/api/v3/PublicHolidays/2025/JP");
  const data = await response.json();
  console.log(data);
}
JavaScript

ここでのポイントは:

  • 関数に async を付けると、中で await が使える
  • await fetch(...) は「fetch が終わるまで待つ」
  • await response.json() は「JSON に変換されるまで待つ」

という意味になります。

見た目は「普通の順番のコード」なのに、
中身はちゃんと非同期処理になっている、というのが強みです。


エラーハンドリングの基本:try / catch

なぜエラーハンドリングが必要なのか

API 通信では、いろんな失敗が起こり得ます。

  • ネットが切れている
  • サーバーが落ちている
  • URL を間違えた
  • サーバーが 500 エラーを返している
  • JSON の形式が想定外

これらを放置すると、
ユーザーには「何も起きない」「真っ白」のように見えてしまいます。

そこで使うのが try / catch です。

try {
  // うまくいくかもしれない処理
} catch (error) {
  // 失敗したときにやる処理
}
JavaScript

これを async / await と組み合わせると、
「失敗したときに、ちゃんとメッセージを出す」
という優しいアプリになります。


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

機能のイメージ

1日目は、こんな最小構成のアプリを目指します。

  • 年を入力(例:2025)
  • 国コードを選択(JP / US / DE など)
  • 「祝日を取得」ボタンを押す
  • Nager.Date API から祝日一覧を取得
  • ローディング表示(「取得中です…」)
  • 通信失敗時にメッセージ表示

これだけで、
API 通信アプリの基本パターンが全部入っています。


HTML のイメージ(頭の中で想像できればOK)

<input id="yearInput" type="number" placeholder="年を入力(例: 2025)" />

<select id="countrySelect">
  <option value="JP">日本 (JP)</option>
  <option value="US">アメリカ (US)</option>
  <option value="DE">ドイツ (DE)</option>
</select>

<button id="fetchButton">祝日を取得</button>

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

JavaScript では、これらの要素を取得して使います。


DOM 要素を取得する

const yearInput = document.getElementById("yearInput");
const countrySelect = document.getElementById("countrySelect");
const fetchButton = document.getElementById("fetchButton");
const statusDiv = document.getElementById("status");
const resultDiv = document.getElementById("result");
JavaScript

ここまではウォーミングアップです。
ここからが本番。


ローディング表示の基本パターン

「今なにしてるか」を伝える UI

API 通信は、数百ミリ秒〜数秒かかることがあります。
その間、ユーザーは「固まった?」と不安になります。

だから、

  • 「取得中です…」と表示する
  • ボタンを無効化して連打を防ぐ

という UI が大事になります。

function startLoading(message) {
  statusDiv.textContent = message || "取得中です…";
  fetchButton.disabled = true;
}

function endLoading() {
  fetchButton.disabled = false;
}
JavaScript

この 2 つの関数を用意しておくと、
どの API 通信でも同じパターンで使い回せます。


Nager.Date API から祝日を取得する関数(1日目の完成形)

ここが今日のメインです。
fetch / async / await / try / catch / ローディング / エラー分岐
が全部入った関数を書きます。

async function fetchHolidays() {
  const year = yearInput.value.trim();
  const countryCode = countrySelect.value;

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

  startLoading("祝日を取得中です…");
  resultDiv.textContent = "";

  try {
    const url = `https://date.nager.at/api/v3/PublicHolidays/${year}/${countryCode}`;
    const response = await fetch(url);

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

    const data = await response.json();

    if (!Array.isArray(data)) {
      statusDiv.textContent = "予期しない形式のデータが返されました。";
      console.error("Unexpected data:", data);
      return;
    }

    if (data.length === 0) {
      statusDiv.textContent = "祝日が見つかりませんでした。";
      resultDiv.textContent = "";
      return;
    }

    statusDiv.textContent = "祝日の取得に成功しました。";
    renderHolidays(data);

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

  } finally {
    endLoading();
  }
}
JavaScript

ここ、ひとつずつ分解していきます。


重要ポイント1:入力チェックは最初に弾く

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

ここで「年が空なら、API を叩かない」という判断をしています。

これは、

  • 無駄な通信をしない
  • エラーを「ユーザーの入力の問題」として早めに伝える

という意味で、とても大事です。


重要ポイント2:response.ok で HTTP エラーを見分ける

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

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

ここで「サーバー側の問題」を検知して、
ユーザーに伝えています。


重要ポイント3:Array.isArray で形式をチェックする

if (!Array.isArray(data)) {
  statusDiv.textContent = "予期しない形式のデータが返されました。";
  console.error("Unexpected data:", data);
  return;
}
JavaScript

Nager.Date API は、通常は「配列」を返します。
でも、将来仕様が変わったり、
プロキシや別のサーバーを経由したりすると、
配列ではないものが返ってくる可能性もゼロではありません。

ここで形式をチェックしておくと、
「おかしなデータが来たときに、原因を追いやすくなる」
というメリットがあります。


重要ポイント4:「該当なし」と「エラー」を分ける

if (data.length === 0) {
  statusDiv.textContent = "祝日が見つかりませんでした。";
  resultDiv.textContent = "";
  return;
}
JavaScript

ここがとても大事です。

「データが 0 件だった」というのは、
エラーではなく“正常な結果” です。

  • 通信は成功している
  • サーバーも正常に動いている
  • ただ、その条件に合う祝日がなかった

というだけなので、
「エラーが起きました」ではなく、
「見つかりませんでした」と伝えるのが正解です。


重要ポイント5:catch では「技術用語をそのまま出さない」

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

ここで、
statusDiv.textContent = error.message;
のようにしてしまうと、
ユーザーには意味がわからない英語のメッセージが出ることがあります。

ユーザーに見せるメッセージは、
「状況がイメージできる日本語」 にするのが大事です。

一方で、
console.error(error);
で開発者向けの情報はちゃんと残しておきます。


祝日一覧を画面に表示する

シンプルな表示関数

function renderHolidays(data) {
  let html = "<h3>祝日一覧</h3>";

  data.forEach((item) => {
    html += `<p>${item.date}${item.localName}${item.name})</p>`;
  });

  resultDiv.innerHTML = html;
}
JavaScript

ここでは、

  • date → 日付
  • localName → 現地語の祝日名(日本なら「元日」など)
  • name → 英語名

を表示しています。


ボタンにイベントをつなぐ

fetchButton.addEventListener("click", fetchHolidays);
JavaScript

これで、

  • ボタンを押す
  • fetchHolidays が呼ばれる
  • ローディング開始
  • API から取得
  • 成功 or 失敗で分岐
  • ローディング終了

という一連の流れが完成します。


1日目のまとめ

今日あなたがやったことを、言葉で整理してみます。

  • Nager.Date API の祝日エンドポイントを理解した
  • fetch で API にアクセスする基本形を知った
  • async / await で「待つ」コードを書いた
  • try / catch でエラーを受け止めた
  • response.ok で HTTP エラーを判定した
  • Array.isArray と length でデータの中身をチェックした
  • ローディング表示(startLoading / endLoading)を入れた
  • 通信失敗時に「ユーザー向けの日本語メッセージ」を出した

これらは、どんな API アプリでも共通する“型”です。


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

1日目の本質は、

「API 通信は、fetch → await → JSON → 分岐 → UI という一本の流れでできている」

ということです。

Nager.Date だろうが、天気 API だろうが、翻訳 API だろうが、
この流れは変わりません。

ここを一度、自分の手で書いてみたあなたは、
もう「API ってなんか怖い」から一歩抜けています。

2日目では、この祝日アプリに

  • 年の入力補助
  • 国ごとのプリセット
  • ローディング表示の改善

などを足して、
「ちゃんと使えるツール」に近づけていきます。

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