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

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

ただいまの
回答率

87.49%

Ajax通信が2回実行されてしまう

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 4
  • VIEW 8,940

score 80

表題の件、原因の詳細が分かる方いらっしゃったら解説をお願いしたいです。
追加の情報の要望や、検証方法についても教えて頂ければ幸いです。

前提
AdobeAirを使ってPasoliを使用し、Fericaのカード情報を読み取って、Ajax通信でそのカード情報をPOSTする仕組みを構築しています。
AdobeAirで読み取った情報をJSへ渡し、そこで読み取った情報の展開と、隠されたボタン$("#read")をクリックさせ、以下処理を発火させています。

ボタンの処理のバインドはここ以外では行っていません。

$(function(){
    $("#read").click(function ajaxpost(e) {
        // 多重送信を防ぐため通信完了までボタンをdisableにする
        var button = $(this);
        button.attr("disabled", true);
        set_msg("waiting","読込中")

        var jsondatabody = '"'+'i_media_id'+'":"' + $("#i_media_id").val() + '"';
        jsondatabody += ',"'+'todokede_cd'+'":"' + $("#todokede_cd").val() + '"';

        //送信するJSONデータを作成
        var data = JSON.parse("{"+jsondatabody +"}");

        //URLを取得
        var targeturl =  "ReadPage.html";

        return $.ajax({
            type:"POST",                // method = "POST"
            url:targeturl,        // POST送信先のURL,
            data:JSON.stringify(data),  // JSONデータ本体
            contentType: 'application/json; charset=UTF-8', // リクエストの Content-Type
            cache: false, // キャッシュさせない
            //dataType: "json",           // レスポンスをJSONとしてパースする...(Unicodeに変換しているためコメントアウト)
        })

        .done(function(result) {
            // 成功時処理

            //Jsonにパース
            var json = JSON.parse(unescape(result));

            $(json).each(function(){
                var wktitle = this.title;
                var msgbody = this.msgbody
                var autoClearMs ;

                var audio ;

                audio.load();
                audio.play();

            })
            set_msg("ready","カードをかざして下さい。")

        }).fail(function() {
            // エラー
            alert("読取中にエラーが発生しました。システム管理者へ連絡してください。");
        }).always(function(result) {
            // 完了処理
            button.attr("disabled", false);  // ボタンを再び enableにする

        });

    });
});

症状
画面にはtodokede_cdを変更するボタンがあり、このボタンを押すとサーバーと同期通信を行い、一度画面がリロードされます。
一度画面をリロードした後で上記処理を実施した場合、前回の読み取りデータ+今回の読み取りデータがPOSTされてしまいます。

発生条件
端末によって発生する場合としない場合があります。(OSはいずれもWindows7、IE11で実施してます)
確率も100%起こる端末、10%くらい、0%とさまざまです。。。
また、$("#read")を表示させて画面からボタンクリックした場合の発生率は0%です。
おなじく、F12で開発者モードを開きながら実行した場合も発生率は0%です。

試したこと
上記のとおりF12で開発者モードを開きながら実行すると発生しないためなかなか検証が出来ていません。
①Alertでのデバック

$("#read").click(function ajaxpost(e) {


の下に

alert("a");


を入れてみましたが、2回送信が起こる状況では、アラートが出た時点で前回情報のPOSTが飛んできてしまいます。(OKを押すと今回の情報がとんできます)

②bindをオフ

    $("#read").click(function ajaxpost(e) {


の前に$("#read")ボタンへのクリックバインドをoffにする処理を入れてみましたが、効果はありませんでした。

③ajaxオブジェクトの有無を確認

$("#read").click(function ajaxpost(e) {


の下に

if (jqxhr) {
            return;
        }


を入れ、Ajax通信のところを

return jqxhr= $.ajax({


へ変更したところ、現象は起きなくなりました。
ただ、このjqxhrのif文の中にalertを入れてもalertは起きません。
returnするのをやめた場合2回送信がされてしまうので効果はあると思うのですが…
どういう理論でうまくいってるのかよく分かっていません。

以上です。よろしくお願いいたします。

======================20180302追記
色々といじっていたところ、突然再現していた端末ですら再現率が0%になってしまいました。
発生時とソースを全く同じにしたのですが、全く再現せず…
JSとは関係ないんでしょうかね…もう何もわかりません…

======================20180305追記

<div class="hide">
    <button type="button" class="btn btn-default" name="read" id="read" >読みとり(本来は非表示)</button>
    <button type="button" class="btn btn-default hide" name="read_get_felica_id" id="read_get_felica_id" >カードリーダのオープン(本来は非表示)</button>
</div>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • x_x

    2018/03/02 13:40

    #readのHTMLを提示してもらえないでしょうか?

    キャンセル

回答 1

0

リロード前とリロード後の両方のデータが送信されるということは、クリックイベントを二重登録ではなく、
何らかの原因でリロード前の項目が存在している可能性が高いですね。
(項目が残っているので、その項目にバインドされたイベントも残っている)

なので、原因はリロード処理にある可能性が高いので、リロード処理がわからないとなんとも言えないですね。

また、ajaxの戻り値をjqxhrに代入する処理とjqxhrの判定処理をいれた場合に
何故、二重送信されないのかについては、
クリックイベントの処理が2つ動かされてしまった場合でも、
先にajaxの処理を始めたほうが、jqxhrにjqXHRオブジェクトを代入し、(undefinedではなくなる)
後のほうはif文にてそれを判定して、ajaxを行う前に処理を終了しているだけです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/02/28 11:28

    ぼんやりとした質問にご回答ありがとうございます。
    以下返答させていただきます。(的を射てないかもしれません、すみません…)
    >なので、原因はリロード処理にある可能性が高いので、リロード処理がわからないとなんとも言えないですね
    リロード処理はGETを伴う普通のページ遷移です。ページ遷移を行うと、非同期通信で送っている情報はクリアされるように作成しています。(という認識ですが、残る可能性があるのでしょうか…)

    >後のほうはif文にてそれを判定して、ajaxを行う前に処理を終了しているだけです。
    ありがとうございます。
    この場合return;の前にalert("a");と入れていれば、
    クリックイベント2回目の処理の際にaのポップアップメッセージが表示さるのではないでしょうか?
    表示されず処理が終了する理由についてもご存知でしたら教えて頂きたく…

    キャンセル

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

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

関連した質問

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