すでに「2.」の手順で、
req.onreadystatechange = statechange;
と設定してあるため、XMLHttpRequestオブジェクトのステータスが変化するとstatechangeメソッドが呼び出される。
statechangeメソッドでは、まずステータスをチェックする。ステータスはreadyStateプロパティに入っており、値が「4」であるときには受信完了を示す。
if (req.readyState == 4)
{
// 受信完了
}
受信完了の際には、HTTPのエラーコードを確認する。正しく受信が完了した場合のステータスは「200」だ。
if (req.status == 200)
{
// HTTPの受信は成功した
}
statusプロパティには、サーバエラーが発生した場合に500、ファイルが見つからない時には403といった、通常のHTTPのステータスコードが設定される。
statusプロパティが200であったなら正常終了であり、データを取得できるのだ。
XMLHttpRequestオブジェクトには、データを取得するためのプロパティが2つある。一つはテキスト形式で取得するresponseTextプロパティ、もう一つはXML形式で取得するresponseXMLプロパティだ。
ここではサーバ側からXMLデータが戻ってくるので、次のようにresponseXMLプロパティを使って取り出せばよい。
var xmlobj = req.responseXML;
responseXMLプロパティの戻り値は、DOMのDocumentオブジェクトだ。サーバからのデータは、
<result><add>400</add><diff>200</diff></result>
のように、「和」が「<add>」、「差」が「<diff>」で囲まれているので、次のようにして取り出す。
// 和を取得
var addobj = xmlobj.getElementsByTagName("add");
var addvalue = addobj[0].firstChild.nodeValue;
// 差を取得
var diffobj = xmlobj.getElementsByTagName("diff");
var diffvalue = diffobj[0].firstChild.nodeValue;
そしてDOMを用いて、取得した値を差し込む。
// <span>に設定
document.getElementById('addvalue').innerText = addvalue;
document.getElementById('diffvalue').innerText = diffvalue;
ここで「addvalue」と「diffvalue」は、HTML中に書かれている次の<span>要素だ。
<span id="addvalue"></span>
<span id="diffvalue"></span>
つまり、
<span id="addvalue">受信した和の値</span>
<span id="addvalue">受信した差の値</span>
のように設定され、ユーザーに表示されるコンテンツが変わるというわけだ。
<html>
<head>
<script type="text/javascript">
<!--
var req = null;
function calc()
{
// XMLHttpRequestオブジェクトを作成
if (window.XMLHttpRequest)
{
// ブラウザ内蔵型の場合
req = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
try
{
req = new ActiveXObject("MXSML2.XMLHTTP");
}
catch (e)
{
try
{
req = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (req == null)
{
alert("XMLHttpRequestオブジェクトが取得できません");
return;
}
// 受信時に実行する関数を設定
req.onreadystatechange = statechange;
// パラメータを指定して呼び出す
// (ここではPOSTメソッドを利用)
req.open('POST', 'http://example.jp/calc.php', true);
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
var parameter = "value1=" + encodeURIComponent(document.getElementById('value1').value) + "&" + "value2=" + encodeURIComponent(document.getElementById('value2').value);
req.send(parameter);
}
function statechange()
{
// 要求ステータスが変化したときに呼び出されるイベントハンドラ
if (req.readyState == 4)
{
if (req.status == 200)
{
// 受信完了かつデータが存在する
var xmlobj = req.responseXML;
// 和を取得
var addobj = xmlobj.getElementsByTagName("add");
var addvalue = addobj[0].firstChild.nodeValue;
// 差を取得
var diffobj = xmlobj.getElementsByTagName("diff");
var diffvalue = diffobj[0].firstChild.nodeValue;
// <span>に設定
document.getElementById('addvalue').innerText = addvalue;
document.getElementById('diffvalue').innerText = diffvalue;
}
else
{
// エラー
alert(req.statusText);
}
}
}
// -->
</script>
</head>
<body>
<p>テキストを入力してください。</p>
<form>
<input type="text" id="value1"/><br/>
<input type="text" id="value2"/><br/>
<input type="button" value="送信" onClick="javascript:calc();"/>
</form>
<div>
<p>
和:<span id="addvalue"></span>
</p>
<p>
差:<span id="diffvalue"></span>
</p>
</div>
</body>
</html>
<?php
$value1 = $_POST['value1'];
$value2 = $_POST['value2'];
$addvalue = $value1 + $value2;
$diffvalue = $value1 - $value2;
$result = "<result>" .
"<add>$addvalue</add>" .
"<diff>$diffvalue</diff>" .
"</result>";
header("Content-Type: text/xml");
print $result;
?>
このようにAjaxの基本は、単に、「JavaScriptでHTTP通信をする」というだけに過ぎない。
サンプルコードで見てきたように、JavaScriptですべてのコードを書くと、ソースが長くなり可視性も悪くなってしまう。問題点として、次のものが挙げられる。
1. サーバサイドのXML生成の問題
リスト2では、単純に文字列の結合でXMLを生成したが、構造体や配列を返すということを考えると、XML生成部分が複雑化する恐れがある。
また文字コードをUTF-8で記述する必要があるため、コード変換も必須となる。
2. XML解析の問題
クライアントでは、Documentオブジェクトを使って、サーバーが送信したXMLを解析し、要素をひとつひとつ取り出す必要がある。「1.」とも関係するが、構造体や配列のパースは面倒な処理となる。
3. DOMツリーの操作の問題
ユーザーに表示するテキストは、DOMの操作で比較的容易に変更できる。しかし、例えばマウスのドラッグ&ドロップに追従して要素の位置を移動する、といった処理をしたい場合には、相当複雑なものになる。
このような問題は、クラスライブラリを使うことで解決できる。次回はAjaxアプリケーション開発を手助けするクラスライブラリについて説明していこう。
Copyright © ITmedia, Inc. All Rights Reserved.