レッツトライ!しもしも

エンジニアときどきイラストレーターのしもしもがレッツトライ!したことを描くブログ

Win7のFirefoxのみ発生するAjax通信でのエラーハンドリング

      2017/09/20

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

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

発生したコード

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

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

Ajax中にページ更新する際の注意点

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

jQueryのajaxのレスポンス待ち中にページ遷移するとerrorになるのを何とか回避する方法 – 時々社内ニートのメモ 目指せ非プログラマー

まず、題が何を言っているかというと あるリクエストを jQueryの$.

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

対処法

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

handle ajax error when a user clicks refresh

i apologise if this is something i should be able to look up. all of the terms i wanted were way overloaded.. here is my problem: when i open a page, it fires off a whole series of ajax calls. if …

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

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

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

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

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になる場合を調べていくと、さまざまなパターンがあるようですね。しかも、サーバーからではなく、ブラウザが返すエラーだったり。通信が切断されていたり、時間以内に通信が帰ってこなかった場合に発生します。

XMLHttpRequestのレスポンス ” JavaScript ” 葉

(反転していない)空欄は、レスポンスとプロパティの値が一致していたことを示します。反転している欄は、HTTPのレスポンスとプロパティの値が異なっていたことを示し、そのうち空欄となっているものは、サーバからレスポンスが到達しているものの、XMLHttpRequestのレスポンスとして返されなかったことを示します。また、「”」で囲まれたプロパティ値は、文字列であることを示します。

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

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

HTTPステータスコードを使ってAJAX通信を整理する – おやまのエンジニアリングブログ

クライアントサイドで AJAX通信をハンドリングするときに HTTPの ステータスコードを使うと可読性がアップする上にサーバーもクライアントも 整理できるので非常に便利であることが最近わかったので ここに使い方をここにまとめておきます。 実装例は以下のとおり。 私は以下のエラーに対してハンドリングを入れています。 401: Unauthroized (許可されていない) セッションが無かった場合に使う。セッションが切れていた場合は、440を使う。 403: Forbidden (禁断) ユーザーの権限ではアクセス出来ない場所にアクセスしようとした場合に返す。 404: Not Found (見つからない) ページが見つからなかった時にサーバーが勝手に返す。 409: Conflict (衝突) サーバー皮の状態とリクエストの状態が一致しない時に返す。 410: Gone (無い) リソースは無くなっていて、クライアント側でもリソースを破棄すべき時に返す。 440: Login Expired (ログイン期限切れ) セッションの有効期限が切れた時に使う。 0: Timeout (通信タイムアウト) これだけは特殊で、サーバーからではなく、ブラウザが返すエラー。 通信が切断されていたり、時間以内に通信が帰ってこなかった場合に発生する。 >=500: サーバーエラー系 いわゆるサーバーエラー系全て。 例外 205: Reset Content (コンテンツをリセット) ページのリソースが古い場合にリセットするように支持する時に返す。 ただし、 ステータスコード が200系なので、successの方に仕込む必要がある。

まとめ

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

参考資料

XMLHttpRequest

XMLHttpRequest は、クライアントとサーバーの間でデータを伝送するための機能をクライアント側で提供する API です。ページ全体を再読み込みすることなく、URL からデータを読み出す簡単な方法を提供します。この API によって、ユーザの作業を中断させることなく Web ページの一部を更新することができます。

XMLHttpRequestのレスポンス ” JavaScript ” 葉

(反転していない)空欄は、レスポンスとプロパティの値が一致していたことを示します。反転している欄は、HTTPのレスポンスとプロパティの値が異なっていたことを示し、そのうち空欄となっているものは、サーバからレスポンスが到達しているものの、XMLHttpRequestのレスポンスとして返されなかったことを示します。また、「”」で囲まれたプロパティ値は、文字列であることを示します。

シェアする

 - Tips ,