この記事で分かること
- XMLHttpRequestを使ったGET・POSTの書き方
- 通信完了とHTTPステータスの確認方法
- ネットワークエラー・HTTPエラー・JSON読み取り失敗への対応
- すぐに試せるサンプルと確認手順
- XMLHttpRequestとfetchの使い分け
ページを開き直さずに情報を取得したり、入力した内容を送ったりしたいとき、JavaScriptからどう通信すればよいか迷うことがあります。この記事では、XMLHttpRequestを使う場面と書き方を、動作確認に使えるサンプルを通して説明します。
ただし、この記事のコードは改修案として作成したもので、実行確認はできていません。実行する前提や確認が必要な点は、本文と最後の「確認が必要な点」に記載しています。
XMLHttpRequestとは?まずは通信の流れを知ろう
XMLHttpRequest(XHR)は、JavaScriptからインターネット上の別のコンピューターへ情報を送り、返事を受け取るための機能です。画面全体を開き直さずに通信できます。
XMLHttpRequestは、Webページから情報を送ったり受け取ったりするためのブラウザーの機能です。XHRは、その名前を短くした呼び方です。
Webページに動きや処理を加えるために使われるプログラミング言語です。
Google ChromeやSafariなど、Webページを見るためのアプリです。
このように、画面を待たせずに裏側で情報をやり取りすることを「非同期通信」といいます。XHRは現在も使える機能ですが、新しく書くコードではfetchが選ばれることも多くあります。
時間のかかる作業が終わるまで画面全体を止めず、ほかの操作を続けられる形で情報をやり取りすることです。
Webページから情報を送ったり受け取ったりする、ブラウザーに備わった別の機能です。新しいコードでは、XHRの代わりに使われることがあります。
通信の基本は、JavaScriptが情報を送り、相手側のコンピューターが返事を返す流れです。XHRでは、通信を始める設定をしてから送信し、返事やエラーを受け取ります。
通信の進み方を図で見ると、送信から返事の受け取りまでの関係が分かります。通信中も、画面はほかの処理を続けられます。

あるアプリやサービスの機能や情報を、別のアプリから利用するための窓口です。
XHRの基本は「作成・設定・送信・結果の確認」
XHRの基本的な使い方は、通信に使うものを作り、送信先などを設定し、送信することです。通信結果を受け取る処理は、送信する前に登録しておきます。
Webページや情報の場所を示す、インターネット上の住所です。
下の短い例では、通信先を設定し、通信完了後に返事の内容を表示します。実際の応答を受け取るには、送信先が利用できる状態である必要があります。
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts/1", true);
xhr.onload = () => {
console.log(xhr.status);
console.log(xhr.responseText);
};
xhr.send();
Webページや情報をインターネット上でやり取りするときに使う決まりごとです。
情報を受け取るときに使う通信方法です。
情報を相手側へ送るときに使う通信方法です。
通信が終わった、ボタンが押されたなど、何かが起きたことを知らせる合図です。
上の例では、open()で通信方法と送信先を設定します。最後の引数をtrueにすると、画面を止めずに通信します。send()で実際に送信します。
onloadは、通信が完了したときに呼び出される処理です。通信が完了したことと、相手側が依頼を正常に処理したことは別なので、statusも確認します。
readyStateとstatusは何が違う?
readyStateは、XHRの通信がどこまで進んだかを示します。statusは、通信相手から返ってきた処理結果の数字です。通信の完了と、処理の成功を分けて確認するため、両方を見る場面があります。
| readyState | 状態 | 説明 |
|---|---|---|
| 0 | UNSENT | 通信の準備が始まっていません。 |
| 1 | OPENED | open()で通信方法と送信先を設定しました。 |
| 2 | HEADERS_RECEIVED | 返事の先頭部分を受け取りました。 |
| 3 | LOADING | 返事の内容を受け取っています。 |
| 4 | DONE | 通信が完了しました。 |
readystatechangeは、readyStateが変わるたびに呼び出されます。そのため、処理を一度だけ行いたい場合は、readyState === 4で通信完了を確認してから結果を扱います。
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) {
return;
}
console.log("通信が完了しました");
console.log("HTTPステータス:", xhr.status);
};
通信が完了したとき、成功を200だけに限定してはいけません。通常は200から299までの数字を成功として扱います。たとえば、作成が成功したときに201が返る場合があります。
readyState === 4でも、通信相手がエラーを返していることがあります。onloadはHTTP上のエラーでも呼び出されるため、statusが成功範囲かどうかを別に確認してください。
readyState === 4で通信の完了を確かめ、status >= 200 && status < 300で成功かどうかを確かめます。
GETで情報を受け取る
次の例では、送信先から1件の投稿情報を受け取ります。成功時は返事の文字列をJSONとして読み取り、画面に表示します。
情報を文字で表すときの決まった書き方です。たとえば、名前と値を組み合わせて情報を記録できます。
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts/1", true);
xhr.timeout = 10000;
xhr.onload = () => {
if (xhr.status < 200 || xhr.status >= 300) {
console.error("HTTPエラー:", xhr.status);
return;
}
try {
const post = JSON.parse(xhr.responseText);
console.log(post);
} catch (error) {
console.error("返事をJSONとして読み取れませんでした", error);
}
};
xhr.onerror = () => {
console.error("通信に失敗しました");
};
xhr.ontimeout = () => {
console.error("通信が時間内に完了しませんでした");
};
xhr.send();
JSONの決まりに沿った文字を、JavaScriptで扱える形に読み替える機能です。
この例では、通信が成功した後にだけ返事を読み取ります。返事がJSONの形でない場合や、JSONとして正しくない文字が返った場合は、読み取りに失敗するためtry...catchで処理しています。
処理の途中で問題が起きたときに、プログラムが突然止まらないように対応する方法です。
実行結果の見方:成功すると、受け取った情報が開発者向けの確認画面に表示されます。送信先が利用できない場合は、通信エラーや時間切れのメッセージが表示されます。
プログラムが出した文字やエラーを確認するための、ブラウザーの画面です。
送信先が返す内容や利用状況は変わる場合があります。実行時に表示された内容を確認し、この記事に書かれた結果と異なる場合は、通信先の状態も確認してください。
POSTでJSONを送る
POSTでJSONを送る場合は、JSONを文字列にしてから送ります。また、送る内容がJSON形式だと通信相手に伝えるため、Content-Typeを設定します。これは、JSONを送る場合の設定であり、すべてのPOST通信で同じ指定が必要という意味ではありません。
送った内容がどの種類のデータなのかを相手に伝える情報です。
JavaScriptで扱っている情報を、JSONの決まりに沿った文字列に変換する機能です。
const xhr = new XMLHttpRequest();
const data = {
title: "XHRから送信した投稿",
body: "POSTの練習用データです。",
userId: 1
};
xhr.open("POST", "https://jsonplaceholder.typicode.com/posts", true);
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xhr.timeout = 10000;
xhr.onload = () => {
if (xhr.status < 200 || xhr.status >= 300) {
console.error("HTTPエラー:", xhr.status);
return;
}
try {
const result = JSON.parse(xhr.responseText);
console.log(result);
} catch (error) {
console.error("返事をJSONとして読み取れませんでした", error);
}
};
xhr.onerror = () => {
console.error("通信に失敗しました");
};
xhr.ontimeout = () => {
console.error("通信が時間内に完了しませんでした");
};
xhr.send(JSON.stringify(data));
実行結果の見方:送信が成功すると、送った内容を含む返事が表示されます。練習用の送信先は、送信内容を実際に保存するサービスとは限りません。保存されると決めつけず、送信先の説明と返事を確認してください。
サンプルを試す手順と前提
GET・POSTの例を試すには、JavaScriptを実行できるページにコードを入れ、通信結果をコンソールで確認します。この記事では通信先に練習用の公開URLを使っています。
- JavaScriptを実行できるページを用意します。
- GETまたはPOSTのコードをページに入れます。
- ページをブラウザーで開き、開発者向けの確認画面を表示します。
- コードを実行し、成功時の返事、またはエラーメッセージを確認します。
Webページを作る人が、プログラムの動きやエラーを確かめるためのブラウザー内の画面です。開き方はブラウザーによって異なります。
よくあるエラーと確認方法
HTTPステータスが200番台ではない
通信相手からエラーを知らせる数字が返った場合は、通信自体は完了していても、依頼が成功したとは限りません。onload内でstatusを確認し、返された数字に応じてエラーメッセージを表示します。
if (xhr.status < 200 || xhr.status >= 300) {
console.error("HTTPエラー:", xhr.status);
return;
}
送信先のURL、送信方法、送った内容が送信先の求める形式かを確認してください。具体的な修正方法は、送信先が返す数字や説明によって異なります。
情報をどのような形で書いたり並べたりするかという決まりです。
onerrorが呼び出される
onerrorは、通信そのものが失敗したときに呼び出されます。インターネットへの接続、送信先のURL、ブラウザーの制限を確認してください。詳しい理由が分かる情報を取得できない場合もあるため、HTTPステータスだけで原因を判断できるとは限りません。
通信が途中で途切れたり、通信先に接続できなかったりして、返事を受け取れない状態です。
別のWebサイトへの通信が制限される
ページを置いた場所と通信先が異なると、通信先の設定によってはブラウザーに止められます。この制限をCORSといいます。エラーが出た場合、JavaScriptだけで制限を解除するのではなく、通信先の設定や公式の利用方法を確認します。
Webページとは別の場所にある情報を読み取るとき、読み取りを許可するかを通信先が決める仕組みです。
JSONとして読み取れない
通信が成功していても、返事がJSON形式とは限りません。返事が空の場合や、文章・HTMLなど別の内容の場合は、JSON.parse()で読み取れません。送信先の説明と、実際に返された内容を確認してください。
通信が時間内に終わらない
timeoutに設定した時間を過ぎると、ontimeoutが呼び出されます。時間を延ばす前に、送信先が応答しているか、URLが正しいか、ネットワークに問題がないかを確認します。
同期通信は使わない
XHRは同期通信にもできますが、通信が終わるまで画面の処理が止まるため、画面を操作する通常のWebページでは避けてください。通信中に画面が反応しなくなる原因になります。
ひとつの作業が終わるまで、次の作業を待たせる進め方です。
XMLHttpRequestとfetchの違い
新しく通信処理を書くなら、まずfetchを検討できます。既存のXHRを読む・直す場合や、XHRを使う必要がある場合は、XHRのイベントや状態を理解しておくと役立ちます。
少し時間がかかる処理の結果を、後から受け取るためのJavaScriptの仕組みです。
| 比べる点 | XMLHttpRequest | fetch |
|---|---|---|
| 結果の受け取り方 | onloadなどのイベントで受け取ります。 |
Promiseを使って結果を受け取ります。 |
| HTTPエラーの確認 | 通信完了後にstatusを確認します。 |
返事を受け取った後に、成功かどうかを確認する必要があります。 |
| 既存コードの保守 | XHRで書かれたコードを読むときに必要です。 | 新しいコードを書くときの選択肢になります。 |
どちらを使う場合も、HTTPエラーを自動的に業務上の失敗処理へ置き換えてくれるわけではありません。返事を受け取った後に、成功かどうかを確認してください。
fetchの詳しい書き方は、【JavaScript入門】fetch APIの基本|XHRとの違い・書き方・レスポンス処理を初心者向けに解説を参照してください。エラーの考え方をさらに確認したい場合は、JavaScript APIのエラー処理|原因別の判定と対処【JavaScript入門】も役立ちます。
根拠となる仕様
XHRの状態やイベントの定義は、標準仕様で確認できます。この記事の説明とコードを公開する前に、対象とするブラウザーでの動作とあわせて、人による照合が必要です。
よくある質問(FAQ)
readyState === 4なのに通信に失敗したように見えるのはなぜですか?
4は通信が完了したことを示し、成功したことまでは示しません。onload内でstatusを確認し、2xxの範囲外ならHTTPエラーとして扱います。
onerrorとHTTPエラーは同じですか?
同じではありません。HTTPエラーは通信相手からエラーを示す返事を受け取った状態で、通常はonload内のstatusで確認します。onerrorは、接続できないなど通信そのものが失敗した場合に使います。
POSTで送るときは、いつもContent-Typeが必要ですか?
いつも同じ指定が必要なわけではありません。JSONを送る例では、内容をJSONとして相手に伝えるために指定しています。送信先の説明に合わせて、送るデータの種類と設定を選んでください。
JSON.parse()でエラーになる場合はどうすればよいですか?
まず通信が成功したかを確認し、次に返事の中身がJSON形式かを確認します。返事が空、またはJSONではない場合は読み取れないため、送信先が返す内容に合わせて処理を分けてください。
XHRとfetchはどちらを使えばよいですか?
既存のXHRを保守する場合はXHRの仕組みを理解し、新しい通信処理ではfetchを候補にできます。どちらも、返事の成功確認や通信失敗への対応は必要です。詳しくは【JavaScript入門】fetch APIの基本|XHRとの違い・書き方・レスポンス処理を初心者向けに解説を確認してください。
XHRは今でも使えますか?
XHRは現在も使われている機能です。既存コードの読み書きで必要になることがありますが、新しく書く場合は用途や利用環境を確認して選んでください。
まとめ
- XHRは、ページ全体を開き直さずに情報を送受信する機能です。
- GETは情報の受け取り、POSTは情報の送信に使います。
- 通信完了の確認と、HTTPステータスによる成功確認は別々に行います。
- JSONを送る場合は、送信先の指定に合わせてContent-Typeを設定し、JSON.stringifyで文字列にします。
- 通信失敗・HTTPエラー・JSONの読み取り失敗・時間切れは、原因を分けて確認します。
まずはGETの例を実行し、返事と通信状態を確かめてください。次に、fetchの書き方やエラー処理も学ぶと、通信方法を選びやすくなります。