PR

【初心者向け】JavaScriptの非同期処理とは?Promiseとasync/awaitの仕組みを図解。

未分類
記事内に広告が含まれています。

Promiseは「レストランの呼び出しベル」?JavaScript非同期処理を身近な例で理解。
非同期処理とPromise:データを「箱」から取り出し画面に映すまでのガイド。

なぜ「非同期処理」が必要なのか?

JavaScriptを学び始めると、コードは「上から順に実行される」と教わります。これを同期処理と呼びます。しかし、現代のWeb開発において、同期処理だけではユーザーを不快にさせてしまう大きな壁にぶつかります。

例えば、巨大なデータをダウンロードしている間、JavaScriptがその完了をじっと待っていたらどうなるでしょうか?
JavaScriptは「シングルスレッド(一本の手)」で動いているため、通信が終わるまで画面のスクロールもボタン操作も受け付けない「フリーズ状態」になってしまいます。これを解決し、待ち時間を有効活用するのが非同期処理です。

同期処理と非同期処理の比較

JavaScriptは 一本の手(シングルスレッド)で動いており、一度に一つのことしかできません,。この特徴を念頭に置くと、2つの違いがより理解しやすくなります。

同期処理:一つずつ順番に片付ける「生真面目な仕事」
コードを上から順番に実行し、今やっていることが終わるまで、絶対に次の作業には進みません。

イメージ: レジで注文をして、料理ができあがるまでその場を一歩も動かずに待ち続ける状態です。

メリット: 「Aが終わったらB」という流れが明確で、次に何が起きるか予想しやすいです。

デメリット(ブロッキング): 例えば「巨大なデータのダウンロード」などの時間がかかる仕事があると、その間JavaScriptの「手」がふさがってしまいます。その結果、**画面のスクロールやボタン操作も一切受け付けない「フリーズ状態」**になってしまいます。

非同期処理:待ち時間を有効活用する「せっかちな仕事」
時間のかかる処理を「背景(ブラウザなど)」に任せて、自分はすぐに次の作業へ進む方法です,。

イメージ: レストランで料理を注文し、**「呼び出しベル(Promise)」**を受け取って席に戻る状態です。料理を待っている間(通信中)も、スマホを見たり会話したり(他の操作)ができます。

デメリット: 「あとで実行する」という約束が増えるため、処理が終わる順番がバラバラになりがちです,。そのため、実行順序を整理するための特別な書き方(Promiseやasync/await)を学ぶ必要があります,。

メリット: 重い処理をしていても画面が止まらず、**「止まらない操作感(快適なユーザー体験)」**を実現できます,。GoogleマップやSNSの読み込みなどで活用されています。

非同期処理が支えるユーザー体験(UX)

私たちの身近なサービスは、非同期処理によって「止まらない操作感」を実現しています。

  • GoogleマップやX(旧Twitter): 最初に画面の枠組みだけを表示し、地図や投稿データは後からバックグラウンドで取得して表示します。
  • Gmail: ページ全体をリロードすることなく、新しいメールをリアルタイムに受信・表示できます。
  • Loading画面: データを取得している間も「読み込み中」というアニメーションを表示し、ユーザーが操作を続けられるようにします。

まずは非同期処理の代表的なイメージである『タイマー』を例に、動作の順序を確認しましょう。

処理の順序を整理する:setTimeoutから学ぶ非同期の挙動

非同期処理の感覚を掴むために、setTimeout(指定時間後に処理を実行するタイマー)の動きを見てみましょう。
JavaScriptは「手が一本」しかありませんが、非常に「せっかち」なのです。

console.log(“A”);

setTimeout(() => {
console.log(“B”);
}, 1000);

console.log(“C”);

このコードを実行すると、出力順は 「A → C → B」 になります。

  1. console.log(“A”):即座に実行され、「A」が表示される。
  2. setTimeout(…):タイマー処理をセットし、JavaScriptは即座に「次の仕事」へ進む。1秒待つのはJavaScript自身ではなく、ブラウザのタイマー機能(背景)に任せます。
  3. console.log(“C”):タイマーの完了を待たずに実行され、「C」が表示される。
  4. タイマー完了:1秒経過後、予約されていた「B」が表示される。

JavaScriptは、自分の手を止めることを嫌います。このように「後で実行する」という約束を管理するのが、次に説明するPromiseの役割です。

Promiseの基本:成功と失敗の「約束」

Promiseとは、非同期処理の結果を待つための「予約チケット」のようなオブジェクトです
イメージを鮮やかにするために、「レストランの呼び出しベル」に例えてみましょう。

  • 待機(Pending):注文を終え、ベルを渡された状態。料理(結果)が出るのを待っています。
  • 成功(Fulfilled / resolve):ベルが振動し、料理が完成した状態。
  • 失敗(Rejected / reject):店員から「材料が切れて作れません(エラー)」と告げられた状態。

Promiseを使うことで、料理が届いた後の行動(成功)と、トラブル時の対応(失敗)をあらかじめ予約しておくことができます。

Promiseが resolve(成功)されたときに実行されます。ここで受け取ったデータ(料理)を使って、画面に表示するなどの次の処理を行います。

Promiseが reject(失敗)されたときに実行されます。ネットワークの遮断やファイル不足などのトラブルをスマートに処理します。

Promiseの仕組みがわかったところで、この仕組みを最も頻繁に使う『外部データの取得(Fetch API)』の世界へ踏み出しましょう。

Fetch APIとJSON:データの「箱」を受け取る流れ

外部からデータを取得する標準的な武器が Fetch API です。ここで重要なのは、サーバーから届くのはそのままでは使えない「Response(レスポンス)」という大きな箱である、という点です。

データの流転プロセス
データがJSで使える形になるまでには、実は2段階のPromiseを乗り越える必要があります。

  • fetch(url) → Promise (通信開始!返答を待つ)
  • → Response Object (サーバーから返答の「箱」が届いた状態)
    • response.json() → Promise (箱を解析中!完了を待つ)
    • → JavaScriptの配列・オブジェクト (ついにデータとして使える!)

JSONは「データの詰め合わせ箱」
JSON(JavaScript Object Notation)は、データのやり取りに特化した軽量な形式です。

  • JSON.parse: 届いたJSON文字列をJavaScriptのオブジェクトに変換し、プロパティ(obj.nameなど)でアクセス可能にします。
  • JSON.stringify: JavaScriptのオブジェクトを送信用のJSON文字列に変換します。

データは無事に受け取れましたが、ネットワークの世界では常にトラブルの可能性があります。エラーへの備えを学びましょう。

HTTPステータスとエラーハンドリング

通信は常に成功するとは限りません。その成否を教えてくれるのが HTTPステータスコード です。

主要なステータスコード一覧

コード 意味 状態
200〜299 OK 通信成功。 正しいデータが返っています(response.okはtrue)。
404 Not Found クライアントエラー。 URLが間違っているなどの原因でページが見つかりません。
500 Error サーバーエラー。 サーバー側で何らかの不具合が発生しています。

response.ok によるチェックの重要性

実は fetch は、たとえ404エラーであっても「通信自体はできた」として、catch に飛ばず成功扱いにしてしまいます。そのため、200〜299の成功範囲内かどうかを response.ok で確認し、そうでなければ自ら throw new Error でエラーを投げてあげる必要があります。

エラーを乗り越え、正しいデータを手にしたら、いよいよ最終工程である『画面への反映』です。

取得したデータをDOMに展開する

手に入れたデータをHTML要素に変換し、画面を更新(DOM操作)するのが最終目的です。以下の黄金パターンをマスターしましょう。

1. fetchで取得: 外部URLからデータを呼び寄せる。
2. JSONへ変換: response.json() でJSの配列・オブジェクトにする(Promiseの完了を待つ)。
3. 表示用HTML作成: map メソッドなどを使い、データ件数分のHTML文字列を組み立てる。
4. innerHTMLで反映: 作成したHTMLをDOMの適切な位置に流し込む。

この「部分更新」ができるようになると、ページ全体の再読み込みが不要になり、パフォーマンスと操作性が劇的に向上します。

ここまでがPromiseの基本ですが、さらに直感的に書ける『async/await』という現代的な書き方についても触れておきましょう。

async/await でコードをより読みやすく

Promiseの .then() を何個も繋げる手法(Promiseチェーン)は、処理が増えるとコードが縦に長く伸び続け、通称「クリスマスツリー」や「コールバック地獄」のような読みにくさを招きます。これを解決するのが async/await です。

書き方の比較

// Promiseチェーン(縦に長く、条件分岐が混ざると読みにくい)
fetch(“/data.json”)
.then(response => response.json())
.then(data => console.log(data));

// async/await(現代のスタンダード:上から下に同期処理のように読める!)
async function load() {
try {
const response = await fetch(“/data.json”);
if (!response.ok) throw new Error(HTTPエラー: ${response.status});

    const data = await response.json(); // 解析完了を待ってから次へ
    console.log(data);
} catch (error) {
    console.error("エラーが発生しました:", error); // 通信失敗も解析失敗もここでキャッチ
}

}

async/awaitのメリット

  • 非同期処理を、あたかも同期処理(上から下への自然な流れ)のように記述できる。
  • try…catch を使うことで、複雑なエラー処理も一箇所にまとめてスッキリ書ける。
  • 条件分岐(if文)などが使いやすく、コードの「縦の成長」を抑えられる。

非同期処理とPromise/Fetchの理解は、モダンなWeb開発(ReactやVueなど)へ進むための不可欠な武器になります。

  1. 非同期処理は「待ち時間」をブラウザに任せ、JavaScriptの手(スレッド)を止めないための技術である。
  2. Promiseは「結果の予約チケット」であり、then/catch(または await)を使って未来のデータを受け取る。
  3. Fetch APIは2段階のステップ(Responseの取得 → JSON解析)を経て、データを扱える形に変換する。

基礎が固まったら、次は公開されているAPIを使って「世界の天気」や「最新ニュース」を表示するミニアプリ制作に挑戦してみましょう。データの「箱」を自由に開けられるようになった今のあなたなら、どんな情報でも画面に映し出せるはずです!

YouTube動画

コメント

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