誕生日にもらった意外なもの

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>Ajax</title>
<script type="text/javascript">
<!--
function createXMLHttpRequest(cbFunc) {
XMLhttpObject = new XMLHttpRequest();
if (XMLhttpObject) XMLhttpObject.onreadystatechange = cbFunc;
return XMLhttpObject;
}

function func() {
for (i=0; i<5; i++) {
httpObj = createXMLHttpRequest(displayData);
if (httpObj) {

httpObj.open("GET","file_chk.php?chk=(ファイル名)",true);
httpObj.send(null);

//httpObj.open("POST","file_chk.php",true);
//httpObj.send("chk=(ファイル名)");

}
}
}

function displayData() {
if ((httpObj.readyState == 4) && (httpObj.status == 200)) {
alert(httpObj.responseText);
}
}
// -->
</script>
</head>
<body>
<input type="button" value="Ajax" onclick="func();" />
</body>
</html>

先の投稿と似たものになってしまいますが、以上のようなソースのプログラムを組みました。ボタンを押すとAjaxが作動してphpプログラムを呼び出し、その結果を返すというものです。phpプログラムは任意のファイル名を変数として受け取り、その存在の有無によって返事を返すというものです。ソースは以下の通りです。

<?
$file = $_GET['chk'];
//$file = $_POST['chk'];
if (file_exists($file)) {
print "true";
} else {
print "false";
}
?>

このAjaxで問い合わせるという処理全体をループさせたいのですが、コメントアウトしているPOSTで実行するとうまくいきません。1回しかアラートが出なかったり、5回と設定してるのにそれ以上出たり。当初これに悩まされてましたが、GETで試すとうまくいきました。なぜPOSTだとうまくいかなかったのでしょうか?自分なりに考えてみたのですが全く分かりません。ソースのもので試すときは一方のコメントアウトを外し、他方をコメントアウトさせていました。もちろんphpの方も同様です。

GETとPOSTで書いたソースは間違ってませんよね?同じ意味になってますよね?どちらの方法でもいいことはいいんですが、GETだと与えるクエリによっては行が横に長くなってしまいますし、sendがあるのならそこに変数を書いたほうが見やすいのではないかと思ってPOSTを使ってました。

A 回答 (2件)

post送信の時は、RequestHeaderも送らないとなりません。

open()とsend()の間で、

httpObj.setRequestHeader('Content-Type','application/x-www-form-urlencoded')

などとします。
参考url 以下のサイトが解りやすいかと思います。
送信部分のブラウザ別対処法もしっかりしているので、私もライブラリを使わせて貰っています。
http://allabout.co.jp/career/javascript/closeup/ …

参考URL:http://allabout.co.jp/career/javascript/closeup/ …
    • good
    • 0

> 1回しかアラートが出なかったり、5回と設定してるのにそれ以上出たり。


open()、send()の度に、実際にはonReadyStateChangeが実行されています。(これはXMLHttpRequestオブジェクトの仕様による物です)

変数の使い回しにより、
send()が完了しreadyStateが4、statusが200のまま、
再度openしたりオブジェクトを作り直しすると、onReadyStateChangeによりdisplayData()が呼び出され、
5回以上呼び出されることがあります。
また、open前のreadyStateが0の状態で作り直しすると、displayData()が実行される前にオブジェクトが破棄されますから、1回だけしか実行されないなどの状態になります。

対処方法は配列にするなどして、5回実行されることを保証する様にしてください。


function createXMLHttpRequest() {
XMLhttpObject = new XMLHttpRequest();
return XMLhttpObject;
}

function func() {
for (i=0; i<5; i++) {
httpObj[i] = createXMLHttpRequest();
if (httpObj[i]) {
httpObj[i].onreadystatechange = displayData;
(略 ANo.1参照)
}
}
}

function displayData(obj) {
if (obj.readyState != 4){
return;
}
if(obj.status == 200 || obj.status==304)) {
alert(obj.responseText);
}
}


キャッシュファイル対策もつけています。
メジャーな方法に
URLの後ろに日付をつけるとか、If-Modified-Sinceヘッダをつけるなどして、常に最新のデータを取り直す様にする方法がありますが、
必ず最新のデータでなければならないというのでなければ、
サーバーの負担になるので私はお勧めしません。

displayDataには引数としてXMLHttpRequestオブジェクトが与えられますので、それを使っています。

IE6、IE7の特定の設定時の対策は省略。
ライブラリを使う場合の配列化の必要性はわかりません。
ライブラリのドキュメントやソースコードを見て下さい。

動作未確認。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!