【JavaScript】Ajax - HTTP通信の同期・非同期とGET・POST

【JavaScript】Ajax - HTTP通信の同期・非同期とGET・POST

JavaScriptのAjaxについて解説します。

検証環境

Ajax

Ajaxは『Asynchronous JavaScript + XML』の略称で“Http通信の仕組み”です。

同期処理・非同期処理に対応しており、サーバーとのデータ取得やデータ送信を行うために使用します。

同期・非同期

Http通信はサーバーにリクエストを送信し、結果をレスポンスとして受け取ります。

ネットワークを介した通信のため、一連の処理に多少の時間がかかります。

この一連の処理が完了するまでJavaScriptの処理を一時停止(待機)する方法を同期処理、完了を待たずに次の処理へ移行する方法を非同期処理と呼びます。

手順

Ajaxの基本的な手順は次のとおりです。

  1. 生成
  2. 初期化
  3. リクエスト送信
  4. レスポンス処理

この手順に沿って次の4つの基本的な通信を解説します。

  • 同期: GET
  • 同期: POST
  • 非同期: GET
  • 非同期: POST

同期(GET)

同期処理かつGETリクエストの方法をご紹介します。

生成

XMLHttpRequestのオブジェクトを生成します。

基本構文

new XMLHttpRequest()

サンプル

___ih_hl_start
let request = new XMLHttpRequest();
___ih_hl_end

初期化

Http通信の基本情報を初期化します。

基本構文

変数.open(メソッド, URL, 非同期可否);

サンプル

let request = new XMLHttpRequest();
___diff_start
+request.open('GET', 'https://it-hack.net/api/sample/js/ajax/get/data', false);
___diff_end

送信

Http通信のリクエストを送信します。

基本構文

変数.send()

サンプル

let request = new XMLHttpRequest();
request.open('GET', 'https://it-hack.net/api/sample/js/ajax/get/data', false);
___diff_start
+request.send();
___diff_end

レスポンス処理

Http通信のレスポンスを処理します。
レスポンスのステータスが正常な場合に、データを取り出します。

基本構文

if( request.status == レスポンスステータス ) {
    // レスポンスデータの処理........
}

サンプル

let request = new XMLHttpRequest();
request.open('GET', 'https://it-hack.net/api/sample/js/ajax/get/data', false);
request.send();

___diff_start
+if( request.status == 200 ) {
+    console.log(request.response);
+}
___diff_end
{"A":"aaa","B":"bbb","C":"ccc"}

statusプロパティはレスポンスステータスです。
ステータスはコード(数値)で表わし、一般的には次の意味を持ちます。

コード 意味
200 正常
403 権限なし
404 Not Found
500 サーバーエラー

※ リクエスト先のアプリケーションにより異なる場合があります。

サンプルでは正常(200)の場合にresponseプロパティからレスポンスデータを取得し出力しています。

同期(POST)

POSTリクエスはサーバーにデータを送信する際に使います。
基本は同期(GET)と同じですが、送信データタイプと送信データを設定します。

送信データタイプ

送信するデータのタイプを設定します。
代表的なタイプはHTMLフォームデータ(application/x-www-form-urlencoded)やJSONデータ(application/json)があります。

基本構文

変数.setRequestHeader("Content-Type", データタイプ);

サンプル

let request = new XMLHttpRequest();
request.open('POST', 'https://it-hack.net/api/sample/js/ajax/post/data', false);
___diff_start
+request.setRequestHeader("Content-Type", "application/json");
___diff_end

送信データ

リクエストを送信するsendメソッドの引数にデータを渡します。

基本構文

変数.send(データ);

サンプル

let request = new XMLHttpRequest();
request.open('POST', 'https://it-hack.net/api/sample/js/ajax/post/data', false);
request.setRequestHeader("Content-Type", "application/json");
___diff_start
+request.send(JSON.stringify({ name: 'apple', price: '150' }));
___diff_end

if( request.status == 200 ) {
    console.log(request.response);
}
{"name":"apple","price":"150","code":"XXXX"}

sendメソッドの引数は文字列です。
そのため、JSON.stringifyメソッドによりJSONデータ(オブジェクト)を文字列に変換しています。

このサンプルのリクエスト先は受け取ったJSONデータにcodeプロパティを追加してレスポンスを返しますが、コンソール結果から正常に動作したことが分かります。

非同期(GET)

非同期処理はリクエストの送信後、JavaScriptの実行を停止せずに次の処理へ進みます。

そのため、レスポンスを受け取ったタイミングでレスポンス処理を実行するコールバック関数(レスポンスを受け取ったときに実行する関数)を設定します。

具体的にはオブジェクトの状態を表すreadyStateプロパティとそのプロパティが更新されたタイミングで呼び出されるonreadystatechangeイベントハンドラにコールバック関数を設定し処理を制御します。

readyStateプロパティは数値でオブジェクトの状態を表わします。

数値 意味
0 未初期化
1 初期化済み
2 レスポンス待機
3 レスポンス受信中
4 レスポンス受信完了

レスポンス受信完了を示す4の時にレスポンス処理を行うようコールバック関数を定義します。

また、openメソッドの第3引数をtrueに設定します。

コールバック関数の設定

onreadystatechangeプロパティにコールバック関数を設定します。

基本構文

request.onreadystatechange = コールバック関数

サンプル

let request = new XMLHttpRequest();

___diff_start
+request.onreadystatechange = function() {
+    console.log(request.readyState);
+    if (request.readyState == 4) {
+        console.log(request.response);
+    }
+}
___diff_end

request.open('GET', 'https://it-hack.net/api/sample/js/ajax/get/data', true);
request.send();
1
2
3
4
{"A":"aaa","B":"bbb","C":"ccc"}

コンソール結果からreadyStateプロパティが4の時にレスポンスデータを出力したことが分かります。
また、

非同期(POST)

非同期処理のPOSTリクエストは上記で解説した方法の組み合わせで実現できます。

let request = new XMLHttpRequest();

request.onreadystatechange = function() {
    console.log(request.readyState);
    if (request.readyState == 4) {
        console.log(request.response);
    }
}

request.open('POST', 'https://it-hack.net/api/sample/js/ajax/post/data', true);
request.setRequestHeader("Content-Type", "application/json");
request.send(JSON.stringify({ name: 'apple', price: '150' }));
1
2
3
4
{"name":"apple","price":"150","code":"XXXX"}

非同期(GET)をベースにPOSTリクエストに必要な処理を追加しました。

同期/非同期の比較

同期処理と非同期処理の違いをプログラムの動作で確認するため、sendメソッドのリクエスト送信後にコンソール出力処理を入れて比較します。

同期

let request = new XMLHttpRequest();

request.open('GET', 'https://it-hack.net/api/sample/js/ajax/get/data', false);
request.send();

if( request.status == 200 ) {
    console.log(request.response);
}

console.log("FINISH");
{"A":"aaa","B":"bbb","C":"ccc"}
FINISH

同期処理はレスポンスの受信を待機します。
そのため、コードの順序に沿った実行結果になります。

非同期

let request = new XMLHttpRequest();

request.onreadystatechange = function() {
    if (request.readyState == 4) {
        console.log(request.response);
    }
}

request.open('GET', 'https://it-hack.net/api/sample/js/ajax/get/data', true);
request.send();

console.log("FINISH");
FINISH
{"A":"aaa","B":"bbb","C":"ccc"}

非同期処理はレスポンスの受信を待たずに次の処理に進みます。
そのためHttp通信のタイムラグにより、先にconsole.log("FINISH")が実行されます。