従来のフォーム送信(CGI)とどう違うのか?

 Ajaxを使ってサーバーにデータを送信する場合と従来のフォームを利用した送信の大きな違いは、データのやりとりが同期通信で行われるか、非同期通信で行われるかという点です。これまでのサンプルは全て非同期通信でしたが、XMLHttpRequestのopen()メソッドでは同期通信を行うこともできます。open()メソッドの3番目の引数がフラグになっていて、trueであれば非同期通信、falseであれば同期通信になります。同期通信の場合、従来のフォームを利用した送信と同じになります。つまり、データを送信したらサーバーからデータが戻ってくるのを待つ事になります。この間、スクリプトでは何も制御できません。これに対して、今までやった非同期通信ではサーバーからデータが送られてこなくても様々な処理を行うことができます。
 以下のサンプルで同期通信と非同期通信を体験することができます。できればFirefoxで動作させてください(サンプルを実行する)。サーバー側ではリクエストを受けてから約3秒で応答するようにしています。同期通信のボタンをクリックすると約3秒間何もできないままになります。非同期通信の場合にはボタンクリック後、他の処理を行うことができデータが戻ってきたらメッセージが表示されます。同期通信ではデータを受け取るまでsend()メソッドの次の命令は実行されません。Firefoxの場合データを受け取った時点で(1)のメッセージが表示されます。非同期通信の場合には(1)(2)(3)の順番でメッセージが表示されます。メッセージが表示される順番などはブラウザによって異なります。また、以下のサンプルはInternet Explorerでは(1)が一番最後に処理されます。このため(1)のメッセージが表示されます。これは(1)の行をコメントアウトして実行できないようにしたサンプルで確認できます。(サンプルを実行する

* Internet Explorer 6に関しては動作が怪しいのでFirefoxで動作を確認してみてください。Internet Explorer 6は何かイベントハンドラなどの設定順序などで動作が変わってしまう事もあるらしいので。

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>同期/非同期でデータを送信する</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
function dataSend(asyncFlag)
{
textData = document.ajaxForm.request.value; // 送信するテキストデータを読み出す
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET","save.rb?request="+textData,asyncFlag);
httpObj.send(null);
$("result").innerHTML = "(1) 送信";
}
}

function displayData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
$("result").innerHTML = "(3) 結果:"+httpObj.responseText;
}else{
$("result").innerHTML = "(2) お待ちください...";
}
}
// --></script>
</head>
<body>
<h1>同期/非同期でデータを送信する</h1>
<form method="get" name="ajaxForm" onSubmit="return false;">
<input type="text" value="sample text" name="request"><br>
<input type="button" value="データを送信(非同期)" onClick="dataSend(true)"><br>
<input type="button" value="データを送信(同期)" onClick="dataSend(false)"><br>
</form>
<div id="result"></div>
</body>
</html>


 Ajaxを利用した場合にサーバーとのデータのやりとりが多くなる可能性があります。このため、提供するサービスによっては高速なサーバーと高速回線が必要になります。特に困るのがサーバー側の負荷です。サーバー側の負荷が高くなればレスポンスは悪くなり快適な動作ができなくなります。なるべくならサーバーの負荷を軽減する方向に持って行くのが良いと思われます。
 例えばサーバー内のJPEGファイル一覧を取得するというプログラムでは、JPEGファイルがあるかどうかをサーバー側で処理しています。同様に検索処理などサーバー側で処理することになります。もし、サーバー側で検索したり調べなければ多少は負荷が軽減されるかもしれません。Ajaxを使えば今までサーバー側で行っていた処理をブラウザ側(クライアント側)で行うことができます。
 先ほどのJPEGファイルを取得するプログラムをサーバー側は単純にファイルリストだけを返し、JPEGファイル一覧を表示するのをブラウザ側で行ってみましょう。サーバーからのデータはresponseTextで受け取ります。ここで使用しているのはUNIXサーバーなので改行コードはLF (10番) になります。ブラウザに表示する際には、この改行コードを<br>タグに置き換えます。JPEGファイルかどうかを調べるには正規表現を使います。サーバーから返される1行の文字列の末尾がファイル名になっています。ファイル名の末尾が.jpgであればJPEGファイルなのでmatch(/\.jpg$/)として末尾に一致するかどうか調べます。一致した場合には表示処理を行います。これを行数分繰り返せばJPEGファイルだけリスト表示させることができます。(実際のサンプルを実行する

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>サーバー内のファイル一覧を取得する(ブラウザ側で処理)</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
function dataSend(callBackFunctionName)
{
httpObj = createXMLHttpRequest(callBackFunctionName);
if (httpObj)
{
httpObj.open("GET","getFileList.rb");
httpObj.send(null);
}
}
// 全てのファイルを表示
function displayAllData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
resultText = httpObj.responseText;
resultText = resultText.replace(/\x0a/g,"<br>");
$("result").innerHTML = resultText;
}else{
$("result").innerHTML = "お待ちください...";
}
}
// 拡張子がJPEGのみ表示
function displayJPEGData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
resultText = httpObj.responseText;
fList = resultText.split(/\x0a/g);
resultText = "";
for (i=0; i<fList.length; i++)
{
flag = fList[i].match(/\.jpg$/);
if (flag)
{
resultText += fList[i]+"<br>";
}
}
$("result").innerHTML = resultText;
}else{
$("result").innerHTML = "お待ちください...";
}
}
// --></script>
</head>
<body>
<h1>サーバー内のファイル一覧を取得する(ブラウザ側で処理)</h1>
<form method="get" name="ajaxForm" onSubmit="return false;">
<input type="button" value="ファイル一覧を取得 (全て表示)" onClick="dataSend(displayAllData)"><br>
<input type="button" value="ファイル一覧を取得 (拡張子がjpgのみ)" onClick="dataSend(displayJPEGData)"><br>
</form>
<div id="result"></div>
</body>
</html>

 もう少し応用するとJPEG画像だけリストアップし表示させることもできます。
従来サーバーで行っていた処理をブラウザ側で行わせると、より柔軟な処理を行う事ができるようになります。あと、ブラウザ側ではサーバーに大量にリクエストを送らないように注意してプログラムを作成する必要があります。

 次項ではGETメソッドを使ってデータを送信してみます。(GETメソッドはすでに何度も使用していますが)

[第四章 2:GETメソッドでデータを送信するへ]
[目次へ]

(2006.1.7)