Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

  1. トップページ
  2. JavaScript実践編 - XMLHttpRequestの使い方(2)

XMLHttpRequestの使い方(2)

みなさまどうも。

続きまして『Ajax』で『POST』をやってみたり通信エラーだった場合の対処法とかをやっていきたいと思います。

というわけで前回の記事で作った以下のファイルを用意しておいて下さい。今回はこれを改造しながらやっていきたいと思います。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Ajaxてすと</title>
</head>
<body>
<script>
var ajax = new XMLHttpRequest();

ajax.open("get", "./test.txt");
ajax.send(); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	console.log(this.response); // 通信結果を出力します。
}, false);
</script>
</body>
</html>

まずは『POST』からやっていきますね。

上記の『ajax.open("get", "./test.txt")』って部分の『get』を『post』に変更しちゃいましょう。

var ajax = new XMLHttpRequest();

ajax.open("post", "./test.txt");
ajax.send(); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	console.log(this.response); // 通信結果を出力します。
}, false);

そしたら『ajax.send()』の『()』の中に送信したいデータを書いちゃって下さい。こんな感じです。

var ajax = new XMLHttpRequest();

ajax.open("post", "./test.txt");
ajax.send("初音ミク"); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	console.log(this.response); // 通信結果を出力します。
}, false);

実はこれだけで『POST』はOKだったりします。『ajax.send()』の『()』の中が『HTTPリクエストボディ』の中身に該当する感じですね。送りたいデータが無ければ『ajax.send()』の『()』の中は空でOKでございます。

※『HTTPリクエストボディ』についてはこちらへどうぞ。

さてここでちょいと注意点があります。もし『JSON』を送りたい、となった場合は『HTTP通信』のルールで『HTTPヘッダー行』に『Content-Type: application/json;charset=UTF-8』を書かないとだめよーってなっています。まあ指定しなくても通信出来ちゃったりするのですがこういうのはちゃんと守ったほうが良いので守る方向でいきましょう。

※『HTTPヘッダー行』についてはこちらへどうぞ。

そしてこれを『XMLHttpRequest』だった場合にどう指定するかというと『.setRequestHeader()』って子がいるのでその子を使って以下のように記述します。

var ajax = new XMLHttpRequest();

ajax.open("post", "./test.txt");
ajax.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); // JSONとしてヘッダーを指定。
ajax.send(JSON.stringify('[0, 1, 2]')); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	console.log(this.response); // 通信結果を出力します。
}, false);

ここちょいと忘れがちなのでご注意ですね。あともういっちょ注意点ですが『.setRequestHeader()』くんは『.open()』の後じゃないと実行できないので注意ですね。なので以下はエラーです。

var ajax = new XMLHttpRequest();
ajax.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); // これはエラーです。

ajax.open("post", "./test.txt");
ajax.send(JSON.stringify('[0, 1, 2]')); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	console.log(this.response); // 通信結果を出力します。
}, false);

こんな感じで『HTTPヘッダー行』に何かを足したい、となったら『Content-Type: application/json;charset=UTF-8』みたいな部分を『:』で分割して最初の部分を『.setRequestHeader()』の第1引数、最後の部分を第2引数に指定すればOKです。

もし『HTTPヘッダー行』に複数の項目を足したいってなったらその分だけ『.setRequestHeader()』を記述しちゃえばOKです。

var ajax = new XMLHttpRequest();

ajax.open("post", "./test.txt");
ajax.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); // こんな感じで複数足せます。
ajax.setRequestHeader("Cache-Control", "no-cache");
ajax.send(JSON.stringify('[0, 1, 2]')); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	console.log(this.response); // 通信結果を出力します。
}, false);

ここまでは大丈夫そうでしょうか。

続いて「通信エラーだったらどうすればいいの?」ってお話なんですがちょいと沢山のパターンがあるもんで全部解説するのはあまり現実的ではないので『ステータスコード』で判定するパターンと受け取った『JSON』とかで判定するパターンの2つを紹介したいと思います。まあ多分この2つでだいたい対応できる予感でございます。

まず『ステータスコード de 対応』なんですがファイルが見つからなかった場合ってサーバー側で特別な事をしない限り『404』な『ステータスコード』が返ってきますよね。それを利用するとこうなります。

var ajax = new XMLHttpRequest();

ajax.open("get", "./hoge.txt");
ajax.send(); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	if(ajax.status === 404) console.log("404だおー");
}, false);

上記でアクセスしようとしてる『./hoge.txt』は存在してないので『404』がになるわけなのですが『.addEventListener』の中の関数に注目です。なにやら『ajax.status』って書いてありますよね。これの『.status』に『ステータスコード』が収まる仕様になっているので『ステータスコード』を元にした判定を入れたい場合はこんな感じにすればOKです。

ただこの時にちょっと問題になるのが『404』になった時の開発ツールのコンソール画面なんですよね。ブラウザで上記の処理を実行させて『404』になった場合は赤字で以下のような出力がされます。

(index):12 GET https://localhost/reps/js-practice/samples/17_01/hoge.txt 404 (Not Found)

ちょっとややこしいのですが『404』も広い意味でエラーの一種といえばエラーの一種なわけですが「処理が停止になるほどの重大なエラーではないというか実はエラーじゃない」みたいなふわっとした感じになってます。

これはどういう事かと言うと、『404』になろうとも通信は成功してるわけで内部的にはエラー扱いされておらず、『try文』とかでエラーをキャッチしたりってことができないんですね。なのでどうあがいても『404』だったらコンソール画面とかに『(index):12 GET https://localhost/reps/js-practice/samples/17_01/hoge.txt 404 (Not Found)』みたいな出力はされちゃうわけです。

var ajax = new XMLHttpRequest();

ajax.open("get", "./hoge.txt");
ajax.send(); // 通信させます。

try{ // try文で『404』は拾えません。
	ajax.addEventListener("load", function(){ // loadイベントを登録します。

	}, false);
}
catch(e){
	console.log("エラーだお");
}

これパット見だとエラーっぽい感じになっちゃうので人によっては嫌がられる事があるんですね。著者も他に大きいエラーが出た時にどこでエラーが出てるのか紛らわしい感じになりがちなのであまり好きではありません。

まあ『404』の場合は他のページの兼ね合いもあってファイルが存在しなかったらやっぱり『404』にしなくちゃならないって部分もあるしJS側でも「ちゃんとパスを記述する」ってことで防げるので問題はないのですが問題はサーバーの内部処理でエラーになった場合ですよね。

通常、通信した時の送信データが変だった場合はステータスコード『400』にして『Bad Request』ってやっちゃうのが昔ながらのやり方だったんですが『Ajax』した場合だと先程と同じようにコンソール画面にエラーっぽく出力されちゃったりします。

んでコンソール画面に出力させたくない、といった場合にどうするのかというと『Bad Request』だった場合でもステータスコードは『200』にしちゃって、送り返す『JSON』とかでエラーかどうかを判定できるようにするって構造にしちゃうわけです。

というわけでちょいとそういう想定で構成して色々と試してみましょう。

まず『test.txt』には以下のように記述します。

{"status": "error"}

サーバー側からエラーな『JSON』が返って来ると想定してそのまま記述した感じですね。この『JSON』の組み方は自由でOKなのでお好きなように構築してしまってください。

んで『index.html』には以下のように記述します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Ajaxてすと</title>
</head>
<body>
<script>
var ajax = new XMLHttpRequest();

ajax.open("get", "./test.txt");
ajax.send(); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。

}, false);
</script>
</body>
</html>

そしたら通信先からは必ず『JSON』が返ってくるわけですので『this.response』と『JSON.parse()』を使って以下のようにします。

var ajax = new XMLHttpRequest();

ajax.open("get", "./test.txt");
ajax.send(); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	var json = JSON.parse(this.response); // 受け取ったJSONをオブジェクト(連想配列)化します。
}, false);

これで上記の『json』には受け取った『JSON』がオブジェクト(連想配列)となって収まってます。あとはその中の『status』で判定すれば良いのでこうなります。

var ajax = new XMLHttpRequest();

ajax.open("get", "./test.txt");
ajax.send(); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	var json = JSON.parse(this.response); // 受け取ったJSONをオブジェクト(連想配列)化します。

	if(json['status'] === "error") console.log("エラーだお");
}, false);

全体のHTMLはこんな感じですね。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Ajaxてすと</title>
</head>
<body>
<script>
var ajax = new XMLHttpRequest();

ajax.open("get", "./test.txt");
ajax.send(); // 通信させます。
ajax.addEventListener("load", function(){ // loadイベントを登録します。
	var json = JSON.parse(this.response); // 受け取ったJSONをオブジェクト(連想配列)化します。

	if(json['status'] === "error") console.log("エラーだお");
}, false);
</script>
</body>
</html>

これでコンソール画面にエラーっぽい出力がされない状態でエラー対応が出来ました。

このテクニックは最近よく使われますのでぜひ覚えておいて下さい。

というわけで『XMLHttpRequest』の使い方は以上になりますね。続いての記事では『投稿フォーム』ってやつをJSで制御してみましょう。

ではこの辺で失礼致します。

この記事は桜舞が執筆致しました。

著者が愛する小型哺乳類

桜舞 春人 Sakurama Haruto

ISDN時代から様々なコンテンツを制作しているちょっと髪の毛が心配な東京在住のプログラマー。生粋のロングスリーパーで、10時間以上睡眠を取らないと基本的に体調が悪い。好きなだけ寝れる生活を送るのが夢。ゲームとスポーツと音楽が大好き。誰か髪の毛を分けて下さい。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。