Ajax 入門、Ajaxとは?、非同期通信、仕組、使い方なども解説|JavaScript入門講座(16)

JavaScript
この記事は約18分で読めます。

Ajax 入門、Ajaxとは?、非同期通信、仕組、使い方なども解説|JavaScript入門講座(16)のPodcast

下記のPodcastは、Geminiで作成しました。

Ajaxの概念とその歴史的意義

Ajax(エイジャックス)は、ウェブ開発の歴史において最も革新的な技術転換の一つとして数えられます。その正式名称である「Asynchronous JavaScript And XML」が示す通り、JavaScriptを用いてブラウザとサーバ間で非同期な通信を行い、ページ全体をリロードすることなく動的にコンテンツを更新する手法を指します 。この技術が登場する以前のウェブは、ユーザが何らかの操作を行うたびにページ全体の再読み込みが発生し、画面が白く反転する「待機時間」を伴うのが一般的でした。しかし、Ajaxの普及によって、デスクトップアプリケーションに近い、滑らかでストレスのないユーザ体験が提供されるようになりました。

Ajaxの定義と語源の変遷

Ajaxという言葉は、2005年にジェシー・ジェームズ・ギャレットによって提唱されました。当初はデータ形式としてXML(Extensible Markup Language)を利用することが想定されていましたが、現代のウェブ開発においては、より軽量でJavaScriptとの親和性が高いJSON(JavaScript Object Notation)が主流となっています 。現在では、XMLを使用していなくても、JavaScriptによる非同期通信全般を「Ajax」と呼ぶことが一般的です 。

従来の通信方式との比較

従来の通信方式(同期通信)とAjax(非同期通信)の決定的な違いは、ブラウザがサーバからの応答を待つ間の振る舞いにあります。

項目同期通信(従来型)非同期通信(Ajax)
画面の更新ページ全体を再読み込みするページの一部のみを更新する
ユーザの操作通信中は操作が中断される通信中も他の操作を継続できる
データの転送量HTML全体を再取得するため多い必要なデータのみを取得するため少ない
サーバ負荷ページ生成のたびに全体を処理するデータ処理に特化できるため効率的

非同期通信のメカニズム

非同期通信を理解するためには、JavaScriptが動作する環境であるブラウザの内部的な仕組み、特に「イベントループ」の概念を知る必要があります。JavaScriptは基本的にシングルスレッド、つまり一度に一つの処理しか実行できない仕組みですが、非同期通信を利用することで、通信処理をブラウザの外側のネットワーク管理部に委ね、メインのスレッドを解放することができます 。

動作のフロー

非同期通信が実行される際、ブラウザ内部では以下のようなプロセスが進行しています。

リクエストの開始: JavaScriptが通信命令を発行します。このとき、メインの処理は停止せず、すぐに次の行のプログラムを実行します 。

バックグラウンド処理: ブラウザのネットワークスタックがサーバへの通信を担当します。この間、ユーザは画面上のボタンを押したりスクロールしたりといった操作を自由に行うことが可能です 。

レスポンスの受信: サーバからデータが返却されると、ブラウザはそれをメモリ上に蓄積します 。

コールバックの実行: 通信が完了したという通知を受け取ったJavaScriptエンジンは、あらかじめ指定されていた処理(コールバック関数やPromiseの解決)を実行し、画面上のDOMを書き換えます 。

プログラム上の「待機」の扱い

非同期通信においては、単に「待つ」という行為が「処理の停止」を意味しない点が重要です。たとえば、洗濯機を回している間に掃除をするようなものであり、洗濯が終わったという通知(完了イベント)を受けてから「洗濯物を干す」という次のステップに進む構造になっています 。この「終わったら実行する」という約束を形式化したものが、現代のJavaScriptにおけるPromiseオブジェクトです 。

XMLHttpRequestからFetch APIへの進化

Ajaxを実現するための技術は、長年にわたり進化を遂げてきました。その中心的な役割を果たしてきたのが XMLHttpRequest と、その現代的な代替である Fetch API です。

伝統的な XMLHttpRequest (XHR)

XMLHttpRequest は、Internet Explorer 5で初めて導入された、Ajaxの祖とも言えるインターフェースです 。イベント駆動型のモデルを採用しており、通信の状態が変わるたびにイベントが発生し、それを監視して処理を行います。

利点: 古いブラウザを含め、ほぼすべての環境で動作する。アップロードやダウンロードの進捗状況を細かく追跡できる機能がある 。

欠点: コードが冗長になりやすく、非同期処理を連続して記述しようとすると「コールバック地獄」と呼ばれる深いネスト構造に陥りやすい 。また、モダンなプログラミングパラダイムであるPromiseに標準で対応していないため、コードの可読性が低くなる傾向があります 。

現代の標準 Fetch API

2015年頃から普及し始めた Fetch API は、Promiseをベースにしたシンプルかつ強力な通信手段です 。現在、Googleなどの主要なテック企業もFetch APIの使用を推奨しており、Web標準としての地位を確立しています 。

特徴XMLHttpRequestFetch API
ベース技術イベント駆動(コールバック)Promiseベース
コードの記述量冗長(設定項目が多い)簡潔(直感的)
エラー処理状態コードを手動で監視catchメソッドやtry-catchを利用
モダン機能サービスワーカーとの連携が困難ストリーム処理やSWと統合

Fetch APIは、サービスワーカーなどの最新のウェブ機能と親和性が高く、通信データをストリーム(逐次処理)として扱うことができるため、大容量データの処理においてもメモリ効率に優れています 。

Fetch APIの実践的な使い方

Fetch APIを用いることで、最小限の記述でサーバとの通信を確立できます。基本となる fetch() メソッドは、リソースのパスを引数に取り、Promiseを返却します 。

データの取得 (GETリクエスト)

最も基本的な使い方は、単にURLを指定する方法です。この場合、デフォルトでGETメソッドが使用されます 。

javascript

fetch('https://api.example.com/data')
 .then(response => {
    // ネットワークエラー以外(404等)でもPromiseは解決されるため、okプロパティを確認する
    if (!response.ok) {
      throw new Error('サーバエラーが発生しました');
    }
    return response.json(); // 本文をJSONとして解析する(これもPromiseを返す)
  })
 .then(data => {
    console.log('取得データ:', data);
  })
 .catch(error => {
    console.error('通信エラーまたは解析エラー:', error);
  });

fetch() は、サーバからレスポンスヘッダが返ってきた時点でPromiseを解決します。そのため、HTTPステータスコードが404や500であっても、リクエスト自体が成立していれば「成功(Resolved)」とみなされます 。これを正しく処理するためには、response.ok (ステータスが200〜299の間であるかを示す真偽値)をチェックすることが不可欠です 。

データの送信 (POSTリクエスト)

フォームのデータやJSONオブジェクトをサーバに送信する場合は、第二引数にオプションオブジェクトを指定します 。

javascript

const userData = { name: '山田', age: 30 };

fetch('https://api.example.com/users', {
  method: 'POST', // HTTPメソッドの指定
  headers: {
    'Content-Type': 'application/json' // 送信するデータの形式を通知
  },
  body: JSON.stringify(userData) // データを文字列に変換して本文に設定
})
.then(response => response.json())
.then(result => console.log('保存完了:', result));

主要な設定オプション

fetch() の第二引数には、通信の挙動をカスタマイズするための多くのプロパティが存在します 。

オプション説明
methodGET, POST, PUT, DELETE, PATCH などのHTTPメソッド
headersリクエストヘッダー(Headersオブジェクトまたはプレーンなオブジェクト)
body送信するデータ本体(Blob, FormData, URLSearchParams, 文字列など)
modecors, no-cors, same-origin などのリクエストモード
credentialsCookieなどの認証情報を含めるか(omit, same-origin, include)
cacheキャッシュの利用方針(default, no-store, reload, force-cacheなど)
signalAbortSignalを渡し、リクエストを途中でキャンセルするために使用

async/await による非同期処理の最適化

JavaScriptにおける非同期処理を、より直感的で読みやすいコードにするために導入されたのが async と await です。これはPromiseの糖衣構文(シンタックスシュガー)であり、複雑な非同期ロジックを同期処理のような見た目で記述することを可能にします 。

async/await の基本ルール

async: 関数の定義の前に記述します。このキーワードが付与された関数は、常にPromiseを返却するようになります 。

await: async関数の中でのみ使用可能な演算子です。Promiseの処理が完了し、結果が返るまでその行で処理を一時停止させます 。

実装例の比較

前述のFetch処理を async/await で書き換えると、次のように整理されます。

javascript

async function fetchUserInfo(userId) {
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    
    // エラーハンドリング
    if (!response.ok) {
      throw new Error(`ユーザ情報の取得に失敗しました: ${response.status}`);
    }

    // JSON解析を待機
    const user = await response.json();
    return user;
  } catch (error) {
    // ネットワークエラーや解析エラーをここで捕捉
    console.error('エラーログ:', error.message);
    return null;
  }
}

この記法を採用することで、エラー処理を使い慣れた try...catch 構文で行えるようになり、複数の非同期処理を順番に実行する場合でもコードの階層が深くならないという大きなメリットがあります 。

複数の非同期処理の並列実行

単純に await を並べると、一つひとつの処理が終わるのを待ってから次に進むため、全体の処理時間が長くなります。複数のAPIを同時に呼び出す必要がある場合は、Promise.all を活用することで、すべてのリクエストを並列で実行し、パフォーマンスを最大化できます 。

javascript

async function fetchMultipleData() {
  const [news, weather, stock] = await Promise.all([
    fetch('/api/news').then(r => r.json()),
    fetch('/api/weather').then(r => r.json()),
    fetch('/api/stock').then(r => r.json())
  ]);
  // すべてのデータが揃った状態で次の処理へ
}

セキュリティと同一オリジンポリシー

Ajaxによる通信を行う際、開発者が必ず直面するのが「同一オリジンポリシー(Same-Origin Policy)」というブラウザのセキュリティ制限です。これは、あるサイトから読み込まれたスクリプトが、異なるサイト(オリジン)のリソースに対して不正にアクセスすることを防ぐための仕組みです 。

オリジンの定義

オリジンは、「スキーム(プロトコル)」、「ホスト名(ドメイン)」、「ポート番号」の3つの組み合わせで定義されます。これらの一つでも異なれば、異なるオリジンとみなされます 。

CORS(オリジン間リソース共有)

異なるオリジン間でリソースを共有するための仕組みが CORS (Cross-Origin Resource Sharing) です。サーバ側が特定のHTTPヘッダーを返すことで、ブラウザに対して「このサイトからのリクエストは信頼できるので許可する」と明示的に伝えることができます 。

Access-Control-Allow-Origin: アクセスを許可するオリジンを指定します 。

Access-Control-Allow-Methods: 許可するHTTPメソッドを指定します 。

プリフライトリクエスト: PUT や DELETE メソッド、あるいは特定のヘッダーを含むリクエストを行う際、ブラウザは事前に OPTIONS メソッドを使用してサーバに対応状況を確認します 。これを「プリフライト」と呼びます。

CORSのエラーが発生した場合、セキュリティ上の理由からJavaScriptのコード内からは詳細な原因を特定できません。正確な問題点(どのヘッダーが不足しているか等)を確認するには、ブラウザの開発者ツールの「コンソール」タブを確認する必要があります 。

高度な通信制御と最新のAPI

2026年時点のウェブ開発において、Ajax通信をより制御しやすく、また効率的にするための新機能がいくつか提供されています。

AbortController によるリクエストの中断

ユーザが検索キーワードを次々に入力した場合や、ページを途中で離脱した場合、実行中の古いリクエストは不要になります。AbortController を使用することで、不要になったリクエストを能動的にキャンセルし、リソースの浪費を防ぐことができます 。

javascript

const controller = new AbortController();
const signal = controller.signal;

// リクエスト開始
fetch('/api/heavy-data', { signal }).catch(err => {
  if (err.name === 'AbortError') {
    console.log('リクエストがキャンセルされました');
  }
});

// 任意のタイミングで中断
controller.abort();

AbortSignal.timeout()

一定時間が経過してもレスポンスがない場合に自動で通信を切断する「タイムアウト設定」は、最新のブラウザでは AbortSignal.timeout() を用いて非常に簡単に記述できるようになりました 。

javascript

// 5秒でタイムアウトさせる
fetch(url, { signal: AbortSignal.timeout(5000) });

fetchLater() API

fetchLater() は、2026年現在実験的な機能として注目されている新しいAPIです 。このAPIを使用すると、ユーザがページを閉じたりナビゲートしたりした「後」で送信されるべきリクエストを予約できます。アクセス解析のログ送信など、ページのライフサイクルの最後に発生する通信をより確実に、かつメインスレッドを阻害せずに処理することが可能です 。

応答処理の最適化とストリーム

Fetch APIの強力な特徴の一つに、レスポンスデータを「ストリーム」として扱える点があります。通常、response.json() や response.text() を使用すると、すべてのデータがメモリ上に読み込まれるまで処理が待機されますが、Streams API を利用することで、データの到着に合わせて逐次処理を行うことができます 。

逐次読み込みのメリット

数メガバイトに及ぶ巨大なJSONやテキストデータを取得する場合、すべてをメモリに格納してから処理を行うとブラウザのメモリを圧迫し、動作が重くなる原因となります 。ストリームを利用すれば、チャンク(断片)ごとに処理を回せるため、プログレッシブなデータ表示やメモリ節約が可能になります 。

注意点:ボディの消費

Fetch APIのレスポンスボディは「一度しか読めない」という性質を持っています 。一度 response.json() を呼び出すと、そのボディは消費済み(Disturbed)となり、再度 response.text() などで読み取ることはできません。同じレスポンスを複数回利用する必要がある場合は、読み取りを開始する前に response.clone() を使用して複製を作成しておく必要があります 。

実践的なユースケースと設計指針

Ajaxの活用シーンは多岐にわたりますが、代表的な3つのパターンを挙げます。

1. 検索オートコンプリート

ユーザがテキストボックスに入力を行うたびに、裏側で検索候補をAjaxで取得し、リストとして表示します 。この際、一文字入力ごとにサーバへ負荷をかけないよう、入力が止まってから数百ミリ秒後に送信する「デバウンス処理」と組み合わされるのが一般的です。

2. 無限スクロール

SNSのフィードや検索結果一覧などで、画面の下部までスクロールした際に自動的に次のページのコンテンツを取得・追加します 。ページ遷移を挟まないため、ユーザの閲覧体験を中断させない効果があります。

3. 動的なフォームバリデーション

ユーザが入力したメールアドレスやIDが既に使用されていないかを、送信ボタンを押す前にサーバへ問い合わせて確認します。即時的なフィードバックにより、入力エラーによるストレスを軽減します。

まとめ

Ajaxは登場から20年近くが経過し、その実装手段は XMLHttpRequest から Fetch API 、そして async/await へと劇的に進化しました。今日のウェブアプリケーションにおいて、非同期通信は単なる便利な機能ではなく、標準的な設計基盤となっています 。開発者は、Promiseベースの洗練された構文を活用しつつ、同一オリジンポリシーやCORSといったセキュリティ上の制約を正しく理解する必要があります 。また、AbortController や Streams API といった高度な機能を使いこなすことで、より堅牢でパフォーマンスの高いアプリケーションを構築することが可能になります。最新のWeb APIの動向を常に追い、ユーザにとって最適な非同期通信体験を提供し続けることが、フロントエンドエンジニアの重要な責務と言えるでしょう。

参考資料

1. フェッチ API, https://developer.mozilla.org/ja/docs/Web/API/Fetch_API

2. フェッチ API の使用, https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch

3. Window: fetch() method, https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch

4. 【図解】JavaScriptの非同期処理(async/await)を初心者向けに解説, https://qiita.com/Neuealle-saiyo/items/13a5b741c6ee09b233bd

5. JavaScriptの非同期処理 async/await の使い方を解説, https://techmania.jp/blog/javascript-asynchronous/

6. Fetch: Fetch, https://javascript.info/fetch

7. Window: fetchLater() method, https://developer.mozilla.org/en-US/docs/Web/API/Window/fetchLater

8. オリジン間リソース共有 (CORS), https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

9. async/await入門, https://qiita.com/_lvyuu/items/2d929cabd35863cc0133

10. AbortController, https://developer.mozilla.org/ja/docs/Web/API/AbortController

11. Fetch API の詳細な仕様とインターフェイス, https://developer.mozilla.org/ja/docs/Web/API/Fetch_API

12. AbortSignal, https://developer.mozilla.org/ja/docs/Web/API/AbortSignal

13. CORS のエラーに関する詳細, https://developer.mozilla.org/ja/docs/Web/HTTP/Guides/CORS/Errors

14. Fetch API Streaming response 読み込み 処理 例, https://zenn.dev/kojiroueda/articles/e5a18b2c0dc3d4

15. Ajax 検索オートコンプリート 実装 仕組み 解説, https://qiita.com/waniwaninowani/items/a47cb5574c725c7dee79

16. XMLHttpRequest vs Fetch API 2026 比較, https://memo.ag2works.tokyo/post-4424/

17. Fetch API 2026年 最新機能 fetchLater AbortSignal.timeout 解説, https://zenn.dev/t_tsuge/articles/881d19ca52bf0d

18. JavaScript 非同期通信 初心者向け たとえ話 わかりやすい, https://proglearn.com/javascript-synchronous-asynchronous-explanation/

19. Using readable streams, https://developer.mozilla.org/ja/docs/Web/API/Streams_API/Using_readable_streams

20. XMLHttpRequest(XHR)入門, https://apidog.com/jp/blog/xmlhttprequest-intro/

21. Fetch API and XMLHttpRequest comparison, https://apidog.com/jp/blog/javascript-fetch-ajax/

22. Introduction to fetch, https://web.dev/articles/introduction-to-fetch?hl=ja

23. JavaScript の非同期ネットワークリクエスト(AJAX), https://javascript.info/fetch

24. Fetch API best practices 2026 MDN, https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

コメント

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