Ajaxで通信中に他画面に遷移するとエラー処理が走ってしまうという現象に出くわしました。

これが、Win7のFirefoxのみで現象が発生して、GoogleChrome、IEでは発生しないというクセモノ……。(そもそも、要件にFirefox対応がないのに、突っ込まれまして、対応することになりました……。)

発生したコード

以下のように書いてたんですけど、これだとFirefoxは「fail」オプションのエラー処理が走ってしまう。
※システムがわかるようなもろもろのところは適宜削除・修正しています。

function loadInfoFunction() {
	$.ajax({
		type : "POST",
		url : "path",
		dataType : "json",
		data : {id: 1}
		}
	}).done(function(data) {
		// 実行処理
	}).fail(function(xmlHttpRequest, textStatus, errorThrown) {
		// エラー処理
	});
}

ぐぬぬ……。
調べていくと、対処法が2種類でてきた。

Ajax中にページ更新する際の注意点
Ajaxで通信中にF5などを押してページをリロードすると通信エラーが帰ってきます。

現在、関わっているシステムだと後者が有効でしたので、そちらを詳しく書いてきます。

対処法

上のブログだと、さらに外部リンクがあって、本来はここのお話しに対処法が書かれています。

Attention Required! | Cloudflare

JQueryは、ユーザーがブラウザからURLを更新するか、リンクをクリックするか、URLを変更することによって、ページから離れた場所に移動するとエラーイベントをスローします。
だから、エラーが発生した場合に、判断する条件を加えているのですね。

上のajax通信を修正すると以下のようになります。

function loadInfoFunction() {
	$.ajax({
		type : "POST",
		url : "path",
		dataType : "json",
		data : {id: 1}
		}
	}).done(function(data) {
		// 実行処理
	}).fail(function(xmlHttpRequest, textStatus, errorThrown) {
		if(xmlHttpRequest.readyState == 0 || xmlHttpRequest.status == 0)
			return;  // it's not really an error
		 else
		// エラー処理
	});
}

つまり、何を判断しているの?

上のソースを見る限り、エラーになった場合、判断条件が増えています。
自分の勉強のため、詳しくしらべてみました。

XMLHttpRequest は、クライアントとサーバーの間でデータを伝送するための機能をクライアント側で提供する APIです。

まず、XMLHttpRequest.readyStateプロパティは、リクエストの状態を unsigned short 型の値で返します。

状態 説明
0 UNSENT open() がまだ呼び出されていない。
1 OPENED send() がまだ呼び出されていない。
2 HEADERS_RECEIVED send() が呼び出され、ヘッダーとステータスが通った。
3 LOADING ダウンロード中。responseText は断片的なデータを保持している。
4 DONE 一連の動作が完了した。

もうひとつのxmlHttpRequest.statusプロパティは、リクエストに対するレスポンスのステータスを unsigned short 型の値で返します。この値は HTTP リザルトコードです。たとえば、リクエストが成功した場合、200を返します。

HTTP リザルトコードが0になる場合を調べていくと、さまざまなパターンがあるようですね。しかも、サーバーからではなく、ブラウザが返すエラーだったり。通信が切断されていたり、時間以内に通信が帰ってこなかった場合に発生します。

http://leaf.argyr.net/javascript/xmlhttprequest-response/

上の記事を見る限り、FirefoxはHTTPリザルトコードが408(request timeout)の場合、0を返すそうで。
0: Timeout (通信タイムアウト)って認識で問題なさそう。

突き詰めていくと、以下のブログのように、エラーハンドリングするのがいいのかなって思います。

まとめ

クロスブラウザ対応はなかなか難しいですね。ブラウザの仕様によって対応が変わってきます。あと、Ajax通信にもっと詳しくなっていきたいですね。今回まとめた記事、ご参考になれば幸いです。

参考資料

XMLHttpRequest – Web API | MDN
XMLHttpRequest (XHR) オブジェクトは、サーバーと対話するために使用されます。ページ全体を更新する必要なしに、データを受け取ることができます。これでユーザーの作業を中断させることなく、ウェブページの一部を更新することができ500

http://leaf.argyr.net/javascript/xmlhttprequest-response/