質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.60%

POST処理中のJavascript画面再描画( XMLHttpRequest.readyState の状態表示 )がしたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,273

score 18

目標

(用語や考え方が間違っていたらすみません。)
XMLHttpRequest.readyState (0~4)の状態を画面表示したい

練度

基本的なHTMLとCSSが記述できるレベル
(静的な画面表示を依頼されているなかで問題に遭遇中)

現状

正常終了(XMLHttpRequest.status===200 && XMLHttpRequest.readyState===4)
のときのみ再描画される

Foo.OnCreateSuccess = function() {

// nowLoading 表示
dispLoading('NowLoading'); 

// POST値受取
var hoge = new XMLHttpRequest();
hoge.open('POST', 'https://httpbin.org/post'); // ←適当にPOSTできるサイト
hoge.setRequestHeader('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
var replaceData = POSTする各値をセット;
hoge.send(replaceData);

// 決済開始イベント
hoge.onreadystatechange = function() {
    try{
        if( hoge.status===200 ){
            switch( hoge.readyState ){
              case 2:
                console.log("POST readyState 2/4");
                dispLoading('2/4');
                break;
              case 3:
                console.log("POST readyState 3/4");
                dispLoading('3/4');
                break;
              case 4:
                console.log("POST readyState 4/4");
                dispLoading('4/4');
                if(hoge.responseText.indexOf('success')>0){
                  console.log("success");
                  showPayinfo_after();
                }
                break;
              default:
                dispLoading('connect');
                console.log("HTTP connection success");
                break;
            }
        }else{
          console.log('HTTP error status:' + hoge.status );
          showPayinfo_ng(hoge.status);
        }

    }catch(e){
      console.log('例外を捕捉: ' + e.description);
      showPayinfo_ng('例外を捕捉: ' + e.description);
      return;
    }
  } 

} 
/*------------------------------
Loading 画面表示
------------------------------*/
function dispLoading(msg){

  // #loading があればいったん解除
  removeLoading();

  if( msg == undefined ){ msg = ""; }

  // 画面表示メッセージ
  var dispMsg = "<div class='loadingMsg'>" + msg + "</div>";

  // ローディング画像が表示されていない場合のみ出力
  if($("#loading").length == 0){
    $("body").append("<div id='loading'>" + dispMsg + "</div>");
  }
}

/*------------------------------
Loading 画面解除
------------------------------*/
function removeLoading(){
  $("#loading").remove();
}
/*------------------------------
終了後の画面表示
------------------------------*/
function showPayinfo_after() {
removeLoading();
$('#dialog-box').hide();
$('#dialog-overlay').hide();
$('#message').hide();
$('#before_pay').hide();
$('#after_pay').show();
$('#ng_pay').hide();
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yambejp

    2019/03/04 11:07

    status=200を前提とするのにreadyState=4以外をとって何がしたいのでしょうか?

    キャンセル

  • yoh0811

    2019/03/04 11:38

    yambejp さま
    処理待ち時間が長いため、「2/4→3/4→4/4→success」と進捗の状態表示をしたいのが主な目的です。

    キャンセル

  • yambejp

    2019/03/04 12:31

    回答つけましたが、読み込み開始から読み込み終わりまでを
    単にsetIntervalでLoading画面を出す方がロジックが簡単です

    キャンセル

回答 2

checkベストアンサー

+3

サーバー側の処理のバッファリング次第ですね
なにも対策しないとreadyStateの2,3,4はほぼ同時にシフトします

たとえばサーバー側をPHPで処理する場合こう

  • mypage.htm
<script>
var xhr = new window.XMLHttpRequest();
xhr.open("post","xhr.php");
xhr.send();
xhr.onreadystatechange=function(){
  if(xhr.status == 200){
    switch(xhr.readyState){
    case 2:
      document.querySelector('#load').textContent='Loading ';
      break;
    case 3:
      document.querySelector('#load').textContent+='.';
      break;
    case 4:
      document.querySelector('#load').textContent='';
      document.querySelector('#content').textContent=xhr.responseText;
      break;
    };
  }
}
</script>
<div id="load"></div>
<div id="content"></div>
  • xhr.php
<?PHP
$str='echo " ";';
passthru($str);
ob_flush();
flush();
$str='sleep 3 ; echo " ";';
passthru($str);
ob_flush();
flush();
$str='sleep 1 ; echo " ";';
passthru($str);
ob_flush();
flush();
$str='sleep 2 ; echo "content";';
passthru($str);
ob_flush();
flush();
ob_end_flush();


※OSのwait処理を使うのでOSによってはsleepを
「timeout /t nn > null」のような適当なwaitに変える必要があります

サーバー側に都度ゴミデータを履かせないとreadyState=3が拾えません。
readyState=2を待たないでも読み込み開始のトリガーからreadyState=4までを
setIntervalしてもよいかも。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/04 15:35

    ご指摘いただいたとおり、順番にそれぞれの画面(2/4~4/4)の表示状態で
    止めてみたところ、きちんと表示されていることが確認できました。
    一瞬で通り過ぎていただけだったんですね。

    私の練度が至らずPHPも絡めた処理は実現できませんでしたが、
    setInterval 含め引き続き勉強したいと思います。

    ありがとうございました。

    キャンセル

+2

hoge.status===200 は readyState が 4 になっていないと採れません。

【XMLHttpRequest.status - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/status

【【メモ】XMLHttpRequestのイベントについて - Qiita】
https://qiita.com/ShinyaKato/items/64b6726c361f5377b0f3

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/04 14:05

    当方の環境で試してみたところ、HEADERS_RECEIVED 時点で取れました。

    XHRのサンプルコードを見ると、HEADERS_RECEIVED 時点でレスポンスヘッダを取りに行っているので、ステータスコードだけ取れない、というのも少し変な感じがします。
    https://xhr.spec.whatwg.org/#the-getresponseheader()-method

    キャンセル

  • 2019/03/04 15:01

    確かにそうですね、指摘ありがとうございます。

    キャンセル

  • 2019/03/04 15:28

    Lhankor_Mhyさま
    readyStatus=4 まで 0 から順番に来るものと思って、初期バージョンは case 0,1 もありました(お恥ずかしい)。
    Qiita記事、参考になりました、ありがとうごいざいます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る