近年のWebサイトは、情報を読み込む際にページ全体を更新するのではなく、ページの必要な部分のみを更新することが主流になってきました。
JavaScriptでは、AjaxとXMLHttpRequestオブジェクトを利用することによって、このような実装を行うことができます。

そこで今回は、AjaxとXMLHttpRequestの仕組みについて解説していきます。

Ajax

Ajaxとは、「Asynchronous JavaScript And XML」の略で、JavaScriptでの非同期通信を行いXML形式のデータを取得するまでの通信のことです。
かんたんに言えば、XMLHttpRequestオブジェクトを使ってサーバーと通信を行うことです。

例えば、Ajaxを利用すると、ページをリロードしなくてもページの更新ができるようになります。
現在では、非同期通信でデータを取得する流れのこと自体をAjaxと呼ぶようになり、JSON形式でデータを取得することが一般的になっています。

XMLHttpRequest

XMLHttpRequestとは、WebブラウザとWebサーバーとの間で、データのやり取りを行うために利用するオブジェクトのことです。

XMLHttpRequestを利用したAjax通信の大まかな流れは以下です。

  1. クライアント側がXMLHttpRequestオブジェクトを作成
  2. 作成したオブジェクトをサーバーに送信
  3. サーバー側がXMLHttpRequestオブジェクトに要求されたデータを返す
  4. クライアント側で受け取ったデータを処理

Ajax通信

では、実際にAjax通信の方法を見ていきましょう。

XMLHttpRequestオブジェクトの作成

まずは、XMLHttpRequestオブジェクトの作成が必要です。
以下のように変数に代入して使われます。

let xhr = new XMLHttpRequest();

オブジェクトの初期化

次に、作成したオブジェクトの初期化を行います。

xhr.open(method, URL, [async, user, password]);

openの呼び出しにより、リクエストの設定ができるようになります。
この時点では、まだリクエストは送信されていません。リクエスト前の準備設定のイメージです。

各引数の説明は以下です。

  • method:HTTPリクエストメソッドを指定。多くの場合GETまたはPOSTを使用
  • URL:リクエスト送信先のURLを指定。文字列またはURLオブジェクトでも可
  • async:非同期通信か同期通信の指定。非同期通信にはtrue、同期通信にはfalseと記述
  • userとpassword:認証が必要な場合にユーザー名とパスワードを記述(省略可)

データ形式の指定

リクエストを送信する際に、レスポンスとして受け取りたいデータの形式を指定することができます。
例えば、以下のようにするとJSON形式でデータの受け取りが可能です。

xhr.responseType = 'json';

リクエストの送信

オブジェクトの初期化ができたら、それを送信します。

xhr.send([body]);

sendの呼び出しにより、上記で初期化したリクエストをサーバーに送信することができます。

オブジェクトの初期化時に、POSTメソッドを使用している場合、bodyパラメーターを使用することができます。
GETメソッドの場合、引数は空のままで大丈夫です。

レスポンスに対するイベントハンドラーの指定

上記でリクエストを送ったので、次はレスポンスに対してイベントハンドラーを指定します。

xhr.onload = () => {}
xhr.onerror = () => {}
xhr.onprogress = () => {}

以下は、XMLHttpRequestオブジェクトで用意されているプロパティです。

  • onload:結果の準備が完了した場合の処理(レスポンスがエラーの場合も含む)
  • onerror:リクエスト送信に失敗した場合の処理
  • onprogress:通信中に繰り返しトリガーされる処理

各イベントハンドラーを用いることで、その後の処理を実行することができます。

レスポンスの結果に対する処理の記述

レスポンスには、ステータスコードというものが存在し、いくつか種類があります。

  • 100:処理継続中
  • 200:処理成功
  • 300:リダイレクト
  • 400:クライアントエラー
  • 500:サーバーエラー

これらのステータスコードを使用し、レスポンスの結果内容によって、その後の処理を実行することができます。

if (xhr.status === ステータスコード ) {
  // ステータスによって処理を分ける
}

ステータスコードが200以外の場合、処理がうまくいっていないことが言えます。
そのため、何かしらの不具合があった場合の表現をする際には、xhr.status !== 200のように記述されることがあります。

ここまでが基本のステップです。

これらを踏まえた一連の流れの例が以下です。
ユーザーの情報を取得するための非同期通信を行っています。

const getUser = (userId) => {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    const url = `http://localhost:3000/users/${userId}`;
    xhr.onload = (e) => {
      if (xhr.status === 200) {
        resolve(xhr.response);
      } else {
        reject(JSON.parse(xhr.response));
      }
    }
    xhr.open("GET", url, true);
    xhr.send();
  });
};

getUser(10)
  .then((data) => {
    // その後の処理
  })
  .catch((err) => {
    // その後の処理
  });

まとめ

今回は、AjaxとXMLHttpRequestについて解説しました。

普段Webページを通じて、さまざまな情報が送受信されている背景には、クライアントとサーバーとの通信の仕組みによって行われていることが分かりました。
XMLHttpRequestには、さまざまなメソッドやプロパティが定義されているため、ぜひ使ってみてください。

合わせて読みたいネットワークリクエストシリーズ

第1回:HTTPプロトコルとHTTP通信の仕組み
第2回:AjaxとXMLHttpRequest(当記事)
第3回:JSONデータを扱う方法
第4回:FetchAPIとHTTPリクエスト