Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. JavaScriptPractice - How to Use XMLHttpRequest (Part 2)

How to Use XMLHttpRequest (Part 2) - Japanese Only

みなさまどうも。

続きまして『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で制御してみましょう。

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

This article was written by Sakurama.

Author's beloved small mammal

桜舞 春人 Sakurama Haruto

A Tokyo-based programmer who has been creating various content since the ISDN era, with a bit of concern about his hair. A true long sleeper who generally feels unwell without at least 10 hours of sleep. His dream is to live a life where he can sleep as much as he wants. Loves games, sports, and music. Please share some hair with him.

If you find any errors or copyright issues, please .