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

APP JavaScript
スポンサーリンク

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

中級編 API 通信アプリ 1 日目のテーマは
「fetch と async/await を使って、天気 API から安全にデータを取ってくる」
ことです。

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

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

そして実装としては、

API からデータ取得
ローディング表示
通信失敗時の分岐

までを一気に体験します。

「タイマー」や「ストップウォッチ」と違って、
今度は外の世界(サーバー)と会話するアプリになります。


まずは「API 通信アプリで何を作るか」を決める

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

今日作るのは、こんなシンプルな天気アプリです。

都市名を入力する
「検索」ボタンを押す
WeatherAPI.com から天気情報を取得する
取得中は「読み込み中…」と表示する
成功したら「気温」「天気」を表示する
失敗したら「エラーのメッセージ」を表示する

まずは「1都市の現在の天気を取ってくるだけ」の
最小構成で考えます。

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

<input id="cityInput" placeholder="都市名を入力 (例: Tokyo)" />
<button id="searchButton">天気を取得</button>

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

status は「ローディングやエラー表示」用、
result は「成功時の天気表示」用です。


fetch の基本を「会話」にたとえて理解する

fetch は「サーバーにお願いしに行く関数」

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

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

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

ここで重要なのは、
fetch は「すぐに結果を返さない」ということです。

返してくるのは「Promise」という
“あとで結果がわかるよ”という約束の箱です。


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

Promise は「未来の結果の箱」

fetch を呼ぶと、
すぐにデータが返ってくるわけではなく、
「いつか終わったら教えるね」という箱(Promise)が返ってきます。

then は「終わったらこれをしてね」
catch は「失敗したらこれをしてね」

という“予約”です。

fetch(url)
  .then((response) => {
    // 成功時
  })
  .catch((error) => {
    // 失敗時
  });
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 が終わるまで、ここで一旦待つ」
という意味です。

その代わり、
await を使う関数には必ず async を付けます。


WeatherAPI.com から天気を取得する流れを分解する

URL を組み立てる

WeatherAPI.com の現在の天気 API は、
だいたいこんな形の URL になります。

https://api.weatherapi.com/v1/current.json?key=YOUR_API_KEY&q=Tokyo&lang=ja

YOUR_API_KEY の部分は自分の API キーに置き換えます。
q=Tokyo の部分が「都市名」です。

JavaScript ではこう書けます。

const API_KEY = "YOUR_API_KEY"; // 自分のキーに置き換える
const baseUrl = "https://api.weatherapi.com/v1/current.json";

function buildUrl(city) {
  const params = new URLSearchParams({
    key: API_KEY,
    q: city,
    lang: "ja"
  });
  return `${baseUrl}?${params.toString()}`;
}
JavaScript

URLSearchParams を使うと、
クエリ文字列(?以降)を安全に組み立てられます。


実装の中心:async 関数で「取得 → 分岐 → 表示」を書く

天気取得関数の骨組み

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

searchButton.addEventListener("click", () => {
  const city = cityInput.value.trim();
  if (!city) {
    statusDiv.textContent = "都市名を入力してください。";
    resultDiv.textContent = "";
    return;
  }

  fetchWeather(city);
});

async function fetchWeather(city) {
  // ここに「ローディング表示」「API 通信」「エラー分岐」を書く
}
JavaScript

ここまではイベントの準備です。
本番は fetchWeather の中身です。


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

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

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

async function fetchWeather(city) {
  statusDiv.textContent = "天気情報を取得中です…";
  resultDiv.textContent = "";
  searchButton.disabled = true;

  try {
    const url = buildUrl(city);
    const response = await fetch(url);

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

ここで重要なのは、
「try の前にローディング表示を出す」
という順番です。


エラーハンドリングの重要ポイントを押さえる

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

try-catch で拾えるのは、
主に「通信自体が失敗したとき」です。

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

ここで return してしまえば、
この先の処理は実行されません。

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

fetch は、
サーバーが 404 や 500 を返しても
「エラーとして throw しません」。

なので、自分で response.ok をチェックします。

const response = await fetch(url);

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

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

3段階目:JSON パースのエラー

レスポンスを JSON に変換します。

const data = await response.json();
JavaScript

ここで JSON が壊れていたりすると、
例外が発生する可能性があります。

なので、本当はここも try-catch で囲むのが理想ですが、
1日目は「fetch 全体を try-catch」で十分です。


成功時のデータ表示を作る

WeatherAPI のレスポンスのイメージ

現在の天気 API は、だいたいこんな形の JSON を返します。

{
  "location": {
    "name": "Tokyo",
    "country": "Japan"
  },
  "current": {
    "temp_c": 26.5,
    "condition": {
      "text": "晴れ",
      "icon": "//cdn.weatherapi.com/..."
    }
  }
}

これを使って、
シンプルに「都市名」「気温」「天気」を表示します。

function renderWeather(data) {
  const name = data.location.name;
  const country = data.location.country;
  const temp = data.current.temp_c;
  const text = data.current.condition.text;

  resultDiv.innerHTML = `
    <p>${name} (${country}) の現在の天気</p>
    <p>気温:${temp} ℃</p>
    <p>状況:${text}</p>
  `;
}
JavaScript

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

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

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

ざっくり、こう分けられます。

ネットワークエラー(オフラインなど)
サーバーエラー(500 番台)
クライアントエラー(404, 400 など)
API 独自のエラー(例えば「都市が見つかりません」)

これをユーザーにとって意味のあるメッセージに変えます。

具体的な分岐例

async function fetchWeather(city) {
  statusDiv.textContent = "天気情報を取得中です…";
  resultDiv.textContent = "";
  searchButton.disabled = true;

  try {
    const url = buildUrl(city);
    const response = await fetch(url);

    if (!response.ok) {
      if (response.status === 400 || response.status === 404) {
        statusDiv.textContent = "指定された都市の天気が見つかりませんでした。";
      } else {
        statusDiv.textContent = `サーバーエラーが発生しました。(${response.status})`;
      }
      return;
    }

    const data = await response.json();

    statusDiv.textContent = "取得に成功しました。";
    renderWeather(data);
  } catch (error) {
    statusDiv.textContent = "通信に失敗しました。ネットワークを確認してください。";
    console.error(error);
  } finally {
    searchButton.disabled = false;
  }
}
JavaScript

ここでのポイントは、

ローディング表示 → 成功 or 失敗メッセージ
ボタン無効化 → finally で必ず元に戻す

という「始まりと終わりの整え方」です。


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

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

fetch は「Promise を返す非同期処理」である
async/await で「同期っぽく書きつつ、try-catch でエラーを扱う」
エラーハンドリングは「ユーザーに意味のあるメッセージに変換する」

そして、
「ローディング表示 → 成功 or 失敗 → 後片付け」
という一連の流れを、
一つの async 関数の中で組み立てられるようになること。

ここまでできたら、
もう「API を叩いてデータを取ってくるアプリ」を
自分で設計できる入り口に立っています。

次の 2 日目では、
この天気アプリに「入力バリデーション」や
「複数日の天気」「エラー内容の詳細表示」などを足して、
さらに“実用アプリ”に近づけていきます。

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