データが受け取れなかった場合の処理

 ネットワークで通信を行う場合には、いろいろなエラーが発生することがあります。ここでは、ありがちなエラー処理についてプログラムを作成してみます。なお、xmlhttp.jsの内容は前項のものと同じです。
 まず、ありがちなエラーとしては読み込むべきファイルがない場合です。例えばファイル名の間違いなどもファイルがないというエラーになります。ファイルが存在しない場合にはサーバーからのステータスコードが404になります。よくページを閲覧していくと404 Not Foundのような文字を見かけることがあります。この404はファイルが存在しないことを示す値になります。readyStateプロパティの値が4で、statusプロパティの値が404の場合にはファイルが存在しない時の処理を行います。実際のスクリプトは以下のようになります(サンプルを実行する)。

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>HTTP通信用、エラー処理</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
function loadTextFile()
{
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET","data2.txt",true);
httpObj.send(null);
}
}
function displayData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
document.ajaxForm.result.value = httpObj.responseText;
}
if ((httpObj.readyState == 4) && (httpObj.status == 404))
{
document.ajaxForm.result.value = "ファイルがありません";
}
}
// --></script>
</head>
<body>
<h1>HTTP通信用、エラー処理のサンプル</h1>
<form name="ajaxForm">
<input type="button" value="読み込み" onClick="loadTextFile()"><br>
<textarea name="result" cols="40" rows="5"></textarea>
</form>
</body>
</html>

 ファイルが存在しないというエラー以外にファイルへのアクセスが許可されていない場合やbasic認証に失敗した場合、CGIなどのサーバー内部のエラーなどもあります(*1)。単純に読み込みが完了しなかった場合には全部エラーとして扱う手もあります。エラー別に処理を分ける場合、前に示したサンプルのようにファイルが存在しない場合など1つ2つ程度のエラー時の処理を記述するのであればif命令でも十分です。しかし、ある程度のエラー数を処理したい場合には以下のようにswicth...caseを使うのが一般的です(サンプルを実行する)。

(2006/3/23追記 Windows版Opera 8.53では404でなく304になることがあるとの報告をいただきました。エラーコード処理は200以外はエラーにする方が安全でしょう)

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>HTTP通信用、エラー処理</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
function loadTextFile()
{
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET","data3.txt",true);
httpObj.send(null);
}
}
function displayData()
{
if (httpObj.readyState == 4)
{
switch(httpObj.status)
{
case 200:
txt = httpObj.responseText;
break;
case 403:
txt = "アクセスが拒否されました";
break;
case 404:
txt = "ファイルがありません";
break;
}
document.ajaxForm.result.value = txt;
}
}
// --></script>
</head>
<body>
<h1>HTTP通信用、エラー処理のサンプル</h1>
<form name="ajaxForm">
<input type="button" value="読み込み" onClick="loadTextFile()"><br>
<textarea name="result" cols="40" rows="5"></textarea>
</form>
</body>
</html>

 switch...caseを使ってもエラー数が多くなると大変です。幸いJavaScriptの場合にはハッシュ(連想配列)を使って関数を呼び出すようにすることでステータスコードに応じた処理を簡単に行うことができます。実際のサンプルは以下のようになります(サンプルを実行する)。

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>HTTP通信用、エラー処理</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
function loadTextFile()
{
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET","data3.txt",true);
httpObj.send(null);
}
}
function displayData()
{
if (httpObj.readyState == 4)
{
try {
statusCode[""+httpObj.status]();
}catch(e){
return;
}
}
}
statusCode = new Array();
statusCode["200"] = function (){ document.ajaxForm.result.value = httpObj.responseText; }
statusCode["401"] = function (){ document.ajaxForm.result.value = "認証失敗"; }
statusCode["403"] = function (){ document.ajaxForm.result.value = "アクセスが許可されてません"; }
statusCode["404"] = function (){ document.ajaxForm.result.value = "ファイルがありません"; }
statusCode["500"] = function (){ document.ajaxForm.result.value = "内部エラー"; }
// --></script>
</head>
<body>
<h1>HTTP通信用、エラー処理のサンプル</h1>
<form name="ajaxForm">
<input type="button" value="読み込み" onClick="loadTextFile()"><br>
<textarea name="result" cols="40" rows="5"></textarea>
</form>
</body>
</html>

 statusCode配列の添字の部分にステータスコードを指定し、実行する関数/処理内容を定義するだけで、多くのエラー処理に対応できます。
 次にデータの読み込みが中断された場合について見てみましょう。サーバーからの送信を中断するにはabort()メソッドを使います。これによりデータの送信が中断されます。以下のサンプルはボタンをクリックするとサーバーからの送信を中断するものです(サンプルを実行する。IEでエラーが出る場合は、こちらのサンプルを実行)。

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>HTTP通信用、中断処理</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
function loadTextFile()
{
txt = "";
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET","sample.mov",true);
httpObj.send(null);
}
}
function displayData()
{
txt += httpObj.readyState + " : " + httpObj.status + "<br>";
document.getElementById("result").innerHTML = txt;
}
function httpAbort()
{
httpObj.abort();
txt += "Last : " + httpObj.readyState + " : " + httpObj.status + "<br>";
document.getElementById("result").innerHTML = txt;
}
// --></script>
</head>
<body>
<h1>HTTP通信用、中断処理のサンプル</h1>
<form name="ajaxForm">
<input type="button" value="読み込み" onClick="loadTextFile()"><br>
<input type="button" value="中断" onClick="httpAbort()"><br>
</form>
<div id="result"></div>
</body>
</html>

 実行するとブラウザによって表示結果が変わります。Firefoxでは読み込み中でもステータスが変化するイベントが発生するため、かなり長い行数になります。上記のスクリプトを実行し中断ボタンを押した場合のreadyStateプロパティの値とステータスコードは以下のようになります。

Internet Explorer 6
2 : 200
3 : 200
:
:
3 : 200
4 : 200
Last : 0 : 200

Firefox 1.5
2 : 200
3 : 200
:
:
3 : 200
4 : 200
Last : 0 : 200

Opera 8.5
1 : 0
3 : 200
Last : 0 : 200

Safari 2.02
1 : undefined
2 : 200
3 : 200
Last : 3 : 200

 やはり環境によって結果が異なります。readyState、ステータスコードからは中断されたかどうかは判別できないので、中断した場合にはフラグ変数を用意して処理するのが安全そうです。

 次にタイムアウトの処理を考えます。ネットワークから一定時間応答がないような場合には、回線が切断されたり何かしらの障害が発生したものとして読み込み処理を中断します。タイムアウトに関してはJavaScriptにはsetTimeout()があるので、これを利用します。setTimeout()は指定した時間を経過したら関数を一度だけ呼び出します。時間はミリ秒で指定するのでタイムアウト秒数が180秒の場合には180000の値(180秒×1000ミリ秒)になります。タイムアウト関数ではabort()でデータの読み込みを中断させます。これで、延々とデータ読み込み待ち状態になるのを防ぐことができます。実際のスクリプトは以下のようになります。このスクリプトではタイムアウトを5秒と短く設定しています(サンプルを実行する)。

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>HTTP通信用、タイムアウト処理</title>
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript"><!--
function loadTextFile()
{
txt = "";
httpObj = createXMLHttpRequest(displayData);
if (httpObj)
{
httpObj.open("GET","sample.mov",true);
httpObj.send(null);
timerID = setTimeout("httpAbort()",5000); // タイムアウトを5秒に設定
document.getElementById("result").innerHTML = "データ読み込み中";
}
}
function displayData()
{
if ((httpObj.readyState == 4) && (httpObj.status == 200))
{
clearTimeout(timerID); // タイムアウト用タイマー解除
document.getElementById("result").innerHTML = "読み込み完了";
}
}
function httpAbort()
{
httpObj.abort();
txt += "Timeout 5 sec....<br>";
document.getElementById("result").innerHTML = txt;
}
// --></script>
</head>
<body>
<h1>HTTP通信用、タイムアウト処理のサンプル</h1>
<form name="ajaxForm">
<input type="button" value="読み込み" onClick="loadTextFile()"><br>
</form>
<div id="result"></div>
</body>
</html>

 ここまでで、(最低限)基本的な通信処理とエラー処理をやりましたので、次からは実際のデータを読み込みページ上に表示する処理を行います。

[7:サーバー上のテキストファイルを読み込みページ上に表示するへ]
[目次へ]

(2005.12.21, 2006.9.03修正)