2012-04-24 2 views
4

ヒートマップを構築するクリックトラッキングアプリを作成しています。私は、ユーザが自分のページに挿入して追跡するためのスクリプトを作成しています。リダイレクトする前にサーバーにクリックされたリンクに関する情報を送信

これは、リダイレクトやフォーム送信を必要としない要素でうまく動作します。たとえば、h1またはpなどをクリックすると、完全に正しく動作します。しかし、私がaをクリックした場合、私たちのサーバーへのリクエストは、通常のリダイレクトの前には起こりません。

最後の数日間、私はそれを行うために多くの方法を試しました。まず、JSONPを使用しなければならないクロスドメイン要求だったので、通常のAJAX呼び出しを試みましたが、AJAX呼び出しはリダイレクト前に実行する時間がありませんでした。 async: falseを追加すると問題は解決しましたが、JSONPリクエストでは機能しません。そこで、リダイレクトで移動するのが安全であることを示すフラグ変数を追加し、ajaxコールバックで試行されるまで空のwhileループを使用しました。しかし、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; 
}); 

次のことは、進行中の総AJAX呼び出しがゼロになるまで待機する(私はカウンターが実装されていた)、その後、リダイレクトで上に移動するunloadページイベントを使用することです。これは、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関数も実行フローをブロックしており、要求は発生しません。それはすでに巨大な痛みだ

だけのアイデアの左側には、イベントハンドラからと、クリックされた要素のhrefに手動でリダイレクトまたはフォーム上のsubmit()を呼び出すことよりも、falseを返すことですが、それは非常にに物事を複雑にし、私を信じますさまざまなブラウザでこのスクリプトをデバッグしてください。

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

+0

あなたはpreventDefaultを試しましたか? –

+0

あなたの 'itsSafeToMoveOn' varはどこに宣言されていますか? – sp00m

+0

@ JibiAbraham私はリダイレクトが発生する必要があります、preventDefaultはそれをキャンセルします。 –

答えて

6
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; 
} 
0

私が正しく理解していれば、ページがアンロードされ、リンクhrefに従う前に、あなたのajaxログが完了したかったとします。これは、jQueryでDeferredsを使用することを検討できる最適なケースのようです。

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

これがシナリオであるかどうかを教えてください。そうであれば、私はもっと詳しく説明します。

+0

モーダルウィンドウは使用できませんので、スクリプトはユーザに対して透過的に動作する必要があります。 –

+0

@ maxt3r - 別のページに行きたいが、現在のページにまだ保留中のアイテムがある場合は、ユーザーに知らせてもらえませんか? –

+0

いいえ、このスクリプトは分析に使用され、クライアントはそのことを知ってはいけません。また、ページパフォーマンスにあまり影響を与えてはいけません。 –

0

クッキーやlocalStorageでajaxリクエストに情報を保存し、情報を送信する作業者を作成することができます。クッキーまたは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); 
}); 

を、データをストレージに保存し、ユーザーの後に次のページに進み、この作業員が起動し、サーバーにデータを送信します。

+1

私もその考えを持っていました。それはちょっとしたバックアップ計画ですが、次のページにスクリプトがない可能性が高いので、キャッシュされたリクエストは永遠にCookieに残ります。 –

+1

次のページが別のWebサイトにある場合はどうなりますか? – Alex

0

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

ベストプラクティスは、イベントのデフォルトハンドラをキャンセルしてバブリングすることです(基本的にjQueryでトラッキングコードを作成する場合はfalseを返します)。必要なアクションを実行します他のデフォルトアクションをトリガーします)、アクションとコールバックの可能な組み合わせをすべて再作成するためには慎重な作業が必要です。

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

ただしどちらの方法でもかまいません。

関連する問題