Webサイトは、もう「ただ開いて読むだけ」の時代ではありません。
ボタンを押すと最新ニュースが読み込まれる、ページ遷移なしでエラーメッセージが表示される、位置情報や天気をサッと取ってきて画面に出す──。
こういった”止まらないUI”はすべて「非同期処理」という仕組みで動いています。
この記事では、はじめての人でもついていけるように、
- 同期処理ってなに?
 - 非同期処理ってなに?
 - Promiseは何をしてくれるの?
 - async / await がなぜ読みやすいの?
 - そして実戦編:Fetch APIでサーバーからデータ(JSON)をもらう
 
まで一気に整理していきます。
「難しそう…」って感じていても大丈夫。
順番に読めば「なんで必要なのか」「どこで使うのか」までちゃんとイメージできるようにしていきます。
目次
1. 同期処理(synchronous)とは?まずはここから
同期処理とは、「上から順番に、1つずつ終わらせてから次に進む」やり方のことです。
イメージでいうと、コンロが1口しかないキッチンで料理している状態です。
- まずソースを作る
 - ソースが終わるまでハンバーグを焼けない
 - ソースが完成してから、ようやくハンバーグを焼く
 - 最後にソースをかけて完成
 
同時に複数のことはできないから、常に「待ち」が発生しますよね。これが同期処理です。
プログラム的に言うと:
- 今この行を実行中 → 終わるまで次の行には進まない
 - 関数を呼び出した → その関数の処理が終わるまで、呼び出し元はいったんストップ
 
という流れになります。
同期処理のサンプルコード
function logTaskA() {
  const now = new Date();
  console.log(`TaskAスタート:${now.toLocaleString()}`);
}
function logTaskB() {
  const now = new Date();
  console.log(`TaskBスタート:${now.toLocaleString()}`);
}
// CPUをわざとつかませて「待たせる」処理
function busyBlock(waitMs) {
  const begin = Date.now();
  while (true) {
    const elapsed = Date.now() - begin;
    if (elapsed >= waitMs) {
      return; // 指定ミリ秒経ったら抜ける
    }
  }
}
logTaskA();        // 1. まずAを実行
busyBlock(2000);   // 2. 強制的に2秒ブロック
logTaskB();        // 3. 2秒後にBが実行される
流れはこうです:
logTaskA()がすぐ動くbusyBlock(2000)が2秒間ブロックして止める- 2秒経つまで 
logTaskB()は実行されない 
つまり「A→待つ→B」という順番が必ず守られます。これが同期処理。
2. 非同期処理(asynchronous)とは?「待ってる間に別のことする」
では非同期処理は何が違うのか。
コンロが2口あるキッチンを想像してください。
- コンロ1でソースを煮込みながら
 - コンロ2で同時にハンバーグを焼ける
 
「ソースが終わるまで何もしない」じゃなくて、「待ってる間に別の仕事を進める」ことができます。
これが非同期処理のイメージです。
プログラム的に言うと:
- 「〇秒後にこれ動かしておいて」と予約だけして、すぐ次の処理に進む
 - その”予約された処理”は、あとで別タイミングで実行される
 - メインの流れは止まらない
 
なので、ユーザーは「画面が固まってる…」と感じにくくなります。UX(使いやすさ)が上がるんです。
3. 非同期処理の実例:setTimeout
JavaScriptには、すぐに使える代表的な非同期APIとして setTimeout があります。
setTimeout(コールバック関数, 待ち時間ミリ秒)
という形で使います。
「待ち時間ミリ秒が経ったら、このコールバック関数を呼んでね」という予約だけして、呼び出し元は止まらずに次に進みます。
同期版を非同期版に書き直す
さきほどの同期処理コードを、わざと非同期っぽく書き換えるとこうなります。
function logTaskA() {
  const now = new Date();
  console.log(`TaskAスタート:${now.toLocaleString()}`);
}
function logTaskB() {
  const now = new Date();
  console.log(`TaskBスタート:${now.toLocaleString()}`);
}
function logAsyncWork() {
  const now = new Date();
  console.log(`あとから実行された処理:${now.toLocaleString()}`);
}
logTaskA();
// 「2秒後にlogAsyncWorkを呼び出してね」と予約だけする
setTimeout(() => {
  logAsyncWork();
}, 2000);
logTaskB();
これを実行すると、だいたいこんな順番になります。
TaskAスタート(すぐ出る)TaskBスタート(Aのすぐ後に出る)- 2秒たってから 
あとから実行された処理 
つまり、setTimeout の部分はすぐには実行されないんです。
「タイマーを仕込んでから、先にBを進める」という動きになる=非同期。
これが「待ってる間に別のことをする」という感覚です。
4. でも非同期はこれで終わらない:Promiseという考え方
setTimeout だけで済むうちはまだいいのですが、現実のWeb開発では「サーバーからデータを取ってくる」「通信が成功したらUIを更新する」「失敗したらエラーメッセージを出す」といったパターンが必須になります。
そこで登場するのが Promise(プロミス)です。
Promiseはなにを約束してくれる?
Promiseは「非同期の結果(成功 or 失敗)を、あとから教えてくれる箱」です。
- 成功したら → 
resolve(...)を呼ぶ - 失敗したら → 
reject(...)を呼ぶ - 呼び出し側は 
.then(...)で成功時の処理を、.catch(...)で失敗時の処理を書ける 
これによって、「いつ終わるかわからない処理」に対して、”終わった後に何をするか”をきれいに書けます。
Promiseの基本形
// 非同期で何かしたい処理をPromiseとして返す関数
function runAsyncDemo() {
  return new Promise((ok, ng) => {
    // ここに非同期の処理を書くイメージ
    const isSuccess = false; // 成功と失敗を切り替えるテスト用フラグ
    if (isSuccess) {
      ok("非同期処理は成功しました!");
    } else {
      ng("非同期処理でエラーが発生しました。");
    }
  });
}
// Promiseを使う側
runAsyncDemo()
  .then((msg) => {
    console.log("成功時のメッセージ:", msg);
  })
  .catch((errMsg) => {
    console.error("失敗時のメッセージ:", errMsg);
  });
ここで大事なのは、
runAsyncDemo()を呼んだ瞬間に結果が返るわけじゃない.then(...)の中は「処理が終わったあと」に呼ばれる.catch(...)には失敗パターンがくる
ということです。
この「終わったあとでやることを登録しておく」という感覚がPromiseの世界観です。
5. Promiseを使って遅延処理を書く(setTimeout版のPromise化)
さっきの「2秒後に実行する処理」をPromise化してみると、もっとイメージしやすいです。
// ログ用の共通メッセージを返すだけの関数
function buildStartLog(label) {
  const now = new Date();
  return `${label} 開始時刻:${now.toLocaleString()}`;
}
// ただの処理A
function showTaskA() {
  console.log(buildStartLog("処理A"));
}
// ただの処理B
function showTaskB() {
  console.log(buildStartLog("処理B"));
}
// 2秒後にメッセージを返すPromise
function waitAndReport() {
  return new Promise((done) => {
    setTimeout(() => {
      // 2秒後に完了扱いにして値を返す
      done(buildStartLog("遅延タスク"));
    }, 2000);
  });
}
showTaskA();
// Promiseの完了後(then)にログを出す
waitAndReport().then((message) => {
  console.log(message);
});
showTaskB();
この場合の実行イメージはこうです:
- 「処理A」ログが出る
 - すぐ「処理B」ログも出る
 - 約2秒後に「遅延タスク」のログが出る
 
waitAndReport() はすぐには結果を返さず、「あとで結果を渡すからね」というPromise(約束)を返しています。
呼び出し側は .then(...) の中に「結果が来たらやること」を書けばOK。
6. async / await:Promiseをもっと読みやすくする書き方
Promiseは便利なんですが、.then(...).then(...).then(...) とネストしていくと、だんだん読みにくくなることがあります。
そこで登場するのが async / await です。
asyncとは?
async function 関数名() { ... } のように async をつけた関数は、自動的にPromiseを返す関数になります。
awaitとは?
await は「このPromiseが解決(完了)するまで、この行でいったん待って。
終わったら結果ちょうだい」という意味になります。
ポイントは、
- awaitはasyncの中でしか使えない
 - ソースコードが「同期っぽい読みやすさ」に近づく
 
ということです。
async/await
// 指定した秒数だけ待ってからメッセージを返すPromise関数
function pauseAndLog(sec) {
  return new Promise((finish) => {
    setTimeout(() => {
      const now = new Date();
      finish(
        `pauseAndLogは${sec}秒待ってから実行されました:${now.toLocaleString()}`
      );
    }, sec * 1000);
  });
}
// async関数:中でawaitが使える
async function runAsyncFlow() {
  // pauseAndLogが完了するまで待って、戻り値をmsgに入れる
  const msg = await pauseAndLog(3);
  console.log(msg);
}
// 比較用の処理
function showAlpha() {
  console.log("showAlpha: 実行開始");
}
function showBeta() {
  console.log("showBeta: 実行開始");
}
// 実行してみる
showAlpha();
runAsyncFlow(); // ← ここで3秒待つが、全体は止まらない
showBeta();
実際の流れはこうなります。
showAlpha()がただちにログを出すrunAsyncFlow()が呼ばれるが、そこで3秒待つPromiseを仕込んでいる- 3秒経ったら 
msgに文章が返ってきてconsole.log(msg)される 
- 3秒経ったら 
 - しかしその待ち時間中も、
showBeta()がすぐ実行される 
await のおかげで、then(...).catch(...) のような形ではなく、”いったん待って結果を受け取る” という自然な読み方ができます。
コードがスッキリしますよね。これが実務でとても重宝します。
7. JSONってなに?なぜみんなJSONでもらいたがるの?
非同期処理が本当に活きるのは「サーバーとデータをやり取りするとき」です。
ここでしょっちゅう登場するのが JSON(JavaScript Object Notation)。
JSONはざっくり言うと「JavaScriptのオブジェクトっぽい見た目をしたデータの表現ルール」です。
例:
{
  "city": "Fukuoka",
  "forecast": ["晴れ", "くもり", "雨"],
  "publishedAt": "2025-10-29T09:00:00+09:00"
}
ポイントは、
{ ... }はオブジェクト[…]は配列"キー": 値のペアでデータが並んでいる- 文字列には基本ダブルクォーテーションを使う
 
JSONは軽くて読みやすいので、APIのレスポンス形式としていま標準的に使われています。
天気予報、ニュース、在庫情報、チャットのログ、フォームの送信結果など、なんでもJSONでもらうことが多いです。
8. Fetch APIでデータを取ってくる(非同期でサーバーにアクセス)
ではいよいよ実戦。
フロントエンド開発でよく使うのが Fetch API です。
Fetch API はブラウザに標準で入っている機能で、URLに対してHTTPリクエストを送り、返ってきたレスポンスをPromiseとして受け取ることができます。
fetch(どこに取りに行くか)- 返ってきたレスポンスを 
.json()でJSONとして読み込む - その結果(オブジェクト)を好きに扱う
 
という流れです。
Fetch APIの基本的な書き方(Promiseスタイル)
// 天気データを配信しているAPIのURL(例)
const endpoint =
  "https://www.jma.go.jp/bosai/forecast/data/forecast/400000.json";
fetch(endpoint)
  .then((res) => {
    // 受け取ったレスポンスをJSONとして解釈
    return res.json();
  })
  .then((weatherData) => {
    console.log("受け取った生データ:", weatherData);
    // 特定エリアのデータを取り出す(例として最初のエリア)
    const targetArea = weatherData[0].timeSeries[0].areas[0];
    console.log("エリア情報:", targetArea);
    console.log("エリア名:", targetArea.area.name);
    console.log("今日の天気:", targetArea.weathers[0]);
    console.log("明日の天気:", targetArea.weathers[1]);
    console.log("あさっての天気:", targetArea.weathers[2]);
    console.log("発表元:", weatherData[0].publishingOffice);
    console.log("報告時刻:", weatherData[0].reportDatetime);
  })
  .catch((err) => {
    console.error("天気データの取得に失敗しました。", err);
  });
ここでやっていることは、
fetch(...)でサーバーに問い合わせ(非同期)- サーバーから返ってきたレスポンスを 
.json()でオブジェクト化(これも非同期で、Promiseを返す) .then(...)の中で実際のデータを扱う.catch(...)でエラーハンドリング
です。
この取得したデータは、ただconsole.logするだけじゃなく、DOMを書き換えて画面に表示することもできます。
たとえば <div id="weatherBox"></div> にテキストを差し込む、といったことができます。
9. Fetch API × async/await版(より読みやすい書き方)
同じことは async/await でも書けます。
これはとても実戦的です。
async function loadWeather() {
  const apiUrl =
    "https://www.jma.go.jp/bosai/forecast/data/forecast/400000.json";
  try {
    // サーバーにアクセス(ここで結果が返るまで待つ)
    const response = await fetch(apiUrl);
    // レスポンスをJSONとして展開(これも待つ)
    const info = await response.json();
    console.log("取得した天気データ:", info);
    // 特定エリアを取り出す(例として先頭エリア)
    const regionData = info[0].timeSeries[0].areas[0];
    console.log("地域名:", regionData.area.name);
    console.log("きょう:", regionData.weathers[0]);
    console.log("あした:", regionData.weathers[1]);
    console.log("あさって:", regionData.weathers[2]);
    // DOMに表示する例(画面に書き出す)
    const box = document.getElementById("weatherBox");
    if (box) {
      box.textContent = `${regionData.area.name} の天気: ${regionData.weathers[0]}`;
    }
  } catch (e) {
    console.error("天気情報の取得に失敗しました", e);
  }
}
// 使い方
loadWeather();
この書き方だと、
await fetch(...):サーバーから返ってくるのを待つawait response.json():JSONパースが終わるのを待つ- その後は普通の変数として扱える
 
という流れで、同期処理っぽい読み心地になります。
「何がいつ完了するのか」「どこでエラーになるのか」が追いやすいので、メンテもしやすいです。
10. まとめ:なぜ非同期処理は避けて通れないのか
ここまでの話をまとめます。
- 同期処理
- 1つずつ順番に実行
 - 前の処理が終わるまで次に進まない
 - シンプルだけど、待ち時間が長いと画面が止まってしまう
 
 - 非同期処理
- 「あとでやって」と予約して、すぐ次の処理に進める
 - ユーザーにとって待ち時間のストレスが減る
 - UIが止まらない・使いやすくなる
 
 - Promise
- 非同期処理の「成功」「失敗」「結果の値」を表現する仕組み
 .then(...)/.catch(...)で後続処理が書ける
 - async / await
- Promiseをもっと読みやすく書くための文法
 awaitで「Promiseが終わるまで一時停止して、結果を受け取る」が自然に書ける
 - Fetch API
- JavaScriptからサーバーにアクセスしてデータを持ってくる標準的な方法
 - 結果はJSONで受け取ることが多い
 - 画面遷移なしで情報を更新できるから、UXが大きく向上する
 
 
あなたがこれを身につけると、「フォームを送信したときに、エラーをその場で出す」「天気予報やニュースを再読み込みなしで表示する」「APIから最新データを引っ張ってきてDOMを書き換える」といった、”いまのWebっぽい”ふるまいが自分で書けるようになります。
もう「静的なページのコーダー」ではなく、「インタラクションまで作れるフロントエンド」に一歩進んだ状態となります。

	
