6

ヒートマップを構築するクリック追跡アプリを作成しています。トラッキングを機能させるために、ユーザーが自分のページに挿入するスクリプトを作成しています。

リダイレクトやフォーム送信を必要としない要素でうまく機能します。たとえば、h1またはその他をクリックするpと、完全に正しく機能します。しかし、をクリックするとa、通常のリダイレクトの前にサーバーへのリクエストが発生することはありません。

ここ数日、私はそれを行うために多くの方法を試しました。まず、JSONP を使用する必要があったクロスドメイン リクエストだったので、通常の AJAX 呼び出しを試みましたが、その AJAX 呼び出しはリダイレクトの前に実行する時間がありませんでした。追加async: falseすれば問題は解決しますが、JSONP リクエストでは機能しません。そのため、リダイレクトを使用しても安全であることを示すフラグ変数を追加し、空の while ループを使用して ajax コールバックで try になるまで待機することにしました。しかし、while ループが実行フローをブロックしていたため、コールバックがその変数を に設定する機会がありませんでしたtrue。単純化されたコードを次に示します。

$(document).on('click', function (e) {
    //part of the code is omitted 
    $.ajax({
        url: baseUrl,
        data: data,
        type: "get",
        dataType: "jsonp",
        crossDomain: true,
        complete: function (xhr, status,) {
            itsSafeToMoveOn = true;
        }
    });

    while(!itsSafeToMoveOn){}

    return true;
});

次に試したのは、unloadページ イベントを使用して、進行中の ajax 呼び出しの合計がゼロになるまで待機し (カウンターを実装しました)、リダイレクトを続行することです。Firefox と IE では機能しましたが、WebKit では次のエラーが発生しました。

Error: Too much time spent in unload handler

その後、サーバーの応答は気にせずimg.src、リクエストに使用することがこのケースに最適であることに気付きました。したがって、この時点でコードは次のようになります。

$(document).click(function (e) {
    //part of the code is ommited
    (new Image).src = baseUrl + '?' + data;

    if (tag === "a" || clickedElement.parents().has("a")) {
        sleep(100); 
    }

    return true;
});

そうすれば、スクリプト全体のパフォーマンスがわずかに向上しますが、リンクの問題は変わりません。sleep関数は実行フローもブロックしているように見え、リクエストは発生しません。

false残っている唯一のアイデアは、イベント ハンドラーから戻り、クリックされた要素に手動でリダイレクトするhrefか、フォームを呼び出すsubmit()ことですが、これは非常に複雑であり、このスクリプトを別の場所でデバッグするのは非常に面倒なことだと思います。ブラウザ。

他のアイデアはありますか?

4

5 に答える 5

7
var globalStopper = true;

$(document).on('click', function (e) {
    if (globalStopper === false)
        return true; //proceed with click if stopper is NOT set
    else {
        globalStopper = false; //release the breaks

        $.ajax({
            //blahblah
            complete: function (xhr, status,) {
                $(elem).click(); //when ajax request done - "rerun" the click
            }
        });
        return false; //DO NOT let browser process the click
    }
});

また、画像を追加する代わりに、スクリプトを追加してみてください。そして、スクリプトを HEAD セクションに追加します。このようにして、ブラウザーはロードされるまで「待機」します。

 $(document).on('click', function (e) {
     var scriptTag = document.createElement("script");
     scriptTag.setAttribute("type", "text/javascript");
     scriptTag.setAttribute("src", url);
     document.getElementsByTagName("head")[0].appendChild(scriptTag);
     return true;
 }
于 2012-04-24T13:19:18.647 に答える
1

ajax リクエストへの情報を Cookie または localStorage に保存し、情報を送信する任意のワーカーを作成できます。Cookie または localStorage への保存は、ajax-request よりも高速です。次のことができます。

$(document).click(function (e) {
    var queue = localStorage.getItem('requestQueue');
    queue.push(data);
    localStorage.setItem('requestQueue',queue);
});

$(function(){
  setInterval(function(){
    var queue = localStorage.getItem('requestQueue');
    while (queue.length > 0) {
      var data = queue.pop();
      $.ajax({
        ...
        success: function(){
          localStorage.setItem('requestQueue', queue);
        }
      });
    }
  },intervalToSendData);
});

したがって、ユーザーがリンクをクリックするかフォームを送信すると、データがストレージに保存され、ユーザーが次のページに移動した後、このワーカーが起動してサーバーにデータが送信されます。

于 2012-04-24T10:18:37.820 に答える
1

JavaScript は基本的にシングルスレッドで実行されます。コールバック関数を実行すると同時に、それからのフラグ変数を待機する無限ループを持つことはできません。無限ループは単一の実行スレッドを占有し、コールバックは呼び出されません。

最善の方法は、イベントのデフォルト ハンドラーとそのバブリングをキャンセルし (実際に jQuery でトラッキング コードを作成している場合は基本的に false を返す)、必要なアクションを実行することです (リンクがクリックまたはトリガーされた場合は、ページを必要なアドレスにリダイレクトします)。他のデフォルト アクション) ですが、アクションとコールバックのすべての可能な組み合わせを再作成するには、多くの慎重な作業が必要になります。

別のアプローチは次のとおりです。1)イベントデータでコードに固有のものを探します2)それが存在しない場合-AJAX呼び出しを行い、そのコールバックで同じ要素でも同じように再トリガーしますが、今回はあなたの偶数データに追加される特定のビット。AJAX 呼び出しが false を返した後 3) データに特定のビットが存在する場合 - 何もせず、デフォルトのイベント処理が行われるようにします。

ただし、どちらのアプローチもかみ合う可能性があります。

于 2012-04-24T12:21:03.663 に答える
0

したがって、私の理解が正しければ、ページがアンロードされてリンク href をたどる前に ajax ログを完成させる必要があります。これは、jQuery でDeferredsを使用することを検討できる完璧なケースのように思えます。

ユーザーがページから離れるはずのものをクリックした場合は、promiseステータスを確認してください。問題が解決しない場合は、ページ上にモーダル ウィンドウを表示し、進行が完了するまでユーザーに待機するように依頼できます。pipe次に、 newをに追加し、すべてが完了したらdeferredを変更するように指示します。location href

これがシナリオかどうか教えてください。もしそうなら、私はより詳細に説明します。あなたの要求をきちんと理解していなければ、続けても意味がありません

于 2012-04-24T09:47:36.857 に答える