2017-06-15 4 views
2

私は、ユーザーが変更できるいくつかのドロップダウンフィルターを含むグラフを持つjavascriptアプリケーションを構築しました。すべてのドロップダウンには(jquery ajax呼び出しを介して)データを取得するためのサーバー要求を送信し、データをグラフ表示するイベントリスナーがあります。問題は、ユーザーがキーボードを使用してドロップダウンのさまざまな要素をすばやく通過する場合です。新しいものが解雇された場合、ajax呼び出しを強制終了する

サーバコールには約1秒かかるため、20秒以内にすばやくスクロールするとビルドアップにつながる可能性があります。サーバーへの20の異なる要求が作成され、サーバー要求の成功で実行されるコードの最後の部分が最新のフィルターになるという保証さえありません。

他のすべての非同期プロセスを強制終了するようにフィルタが変更されたときの私の質問は何ですか?

$("#filter").change(function(d) { 
    getData(); 
} //end of if 
}); 

function getData() { 
    ... 
    $.ajax({ 
    url: myUrl 
    type: "GET", 
    dataType: "json", 
    success: function(d) { 
     [do some stuff] 
     } //end of success function 
    }); //end of ajax 
} //end of getData 
+0

あなたは余分な中かっこを持っています最初の関数で 'if'を閉じていると言っています。 – AtheistP3ace

+0

新しいリクエストを送信する前に、現在実行中のリクエストが完了するまで待つ必要があります(現在のリクエストが実行されている間に発生する可能性のあるリクエストを除外します)。あなたが 'XMLHttpRequest2'の' abort'機能を使用しても、これは依然として不必要な高いサーバ負荷につながります。 –

+0

新しいAJAXコールが作成されたときに、以前のAJAXコールを中止する可能性があります。](https://stackoverflow.com/questions/9285271/abort-previous-ajax-call-when-a-new-one-made) –

答えて

1

保存すべてのAjaxは、あなたが、あなたが最後の呼び出しを中止することができ、いくつかの変数に中止したい呼び出します。ここに関連するコードです。

これは非常に一般的なです。いくつかのajax呼び出しが完了する前に、いくつかのAjax呼び出しが発生する前に実行される場合があります。

function getData(){ 
    $filter.data('REQ') && $filter.data('REQ').abort(); // abort the last request before creating a new one 

    return $.ajax({ 
     url:myUrl 
     type:"GET", 
     dataType:"json", 
     success:function(d){ 
      [do some stuff] 
     } 
    }) 
} 

var $filter = $("#filter"); 

$filter.on('change', function(d) { 
    $filter.data('REQ', getData()) 
}); 

は、もちろん、これはコードの非常に簡略化していると、あなたは、より構造化された方法でこれを書き直す必要がありますが、それはあなたの最後のAJAX要求をキャッシュする方法のアイデアを提供して、あなたが持っています新しいコールを送信する前に、中止する権限。


ところで、あなたのタイトルは質問とは関係ありません。一連のajax呼び出しを処理する方法を尋ねていますが、イベントについて質問しています。この質問はイベントとは関係がないため、問題に合わせてタイトルを変更する必要があります。


更新 t.niese @コメントで言ったことについて:クライアントと、サーバが実際に知ることができないため、クライアント側の要求をスロットリング

は、また、行うには良いプレーですリクエストを中止したかどうかを確認し、リソースが要求されるリクエストの場合は、それを抑制する必要があります。 しかし、クライアント側のスロットルがバイパスされ、100%の信頼性がなく、同じ金額の「コストがかかる」ため、可能であれば、クライアント側ではなくサーバー側で要求を調整することをお勧めしますサーバー側でこれを行う時間を確保する必要があります。

Can a http server detect that a client has cancelled their request?

+1

Ajaxリクエストをグローバルスコープの変数に格納し、その変数をgetDataの先頭で打ち切りをコールしましたが、このアプローチは完璧なおかげで機能しました。 – zachvac

+0

うれしいことですが、私は何か新しいことを学んだことをうれしく思います。 – vsync

+0

'abort'はクライアント側で要求を停止するだけですが、サーバに到達すると、サーバは依然として中断されていても依頼を処理する必要があるかもしれません。したがって、サーバーの負荷に影響を与えない可能性があります。その結果、ボトルネックになった場合、「中止」は役に立たなくなり、放出されるリクエストの数を抑える必要があります。 @ zachvac –

-1

私は、現在の要求の実行中にgetDataを呼び出して新しい要求を開始し、唯一とすぐに現在の要求が完了すると、最後getDataの試行を送信するすべての試みをドロップします。これにより、1つの要求だけが実行されるため、サーバーの負荷が不必要に高くなることはありません。

var currentRequest; 
var resubmitRequest; 

function getData() { 

    // only start a new request id no current request is running 
    if (!currentRequest) { 
    resubmitRequest = false; 
    currentRequest = Promise.resolve($.ajax({ 
     url: myUrl 
     type: "GET", 
     dataType: "json" 
    })); //end of ajax 

    currentRequest 
     .then((d) => { 
     [do some stuff] 
     }) 
     .finally(() => { 
     // if the current request finished and another attempt to request data 
     // happened while this request was running then call getData again 
     if (resubmitRequest) { 
      getData() 
     } 
     }) 

    } else { 
    // store the information that the data has to be requested 
    // another time after the currently running request finished 
    resubmitRequest = true; 
    } 

    return currentRequest; 
} //end of getData 
-1

たとえば、500mil秒間だけ一時停止してから最後の変更を実行し、そのajaxコールを実行するだけです。

場合
$("#filter").change(function(d) { 
    if($.active > 0) return false; 
    // do not run new ajax if last one is not finished 
    clearTimeout(window.timer); 
    // if new 'change' evt is raised in less then 500 mils 
    // then clear it and run 'last' one 
    window.timer = setTimeout(function(){ 
    getData(); 
    }, 500); 
}); 

AJAXをしている間、ユーザーがそれを変更した場合、return falseそれは:)

-1

少ない労力であなたがこれらのケースのためにhandler自分自身をコーディングすることができます

function handler(ms, fn) { 
    var eventId; 
    return function() { 
     // if there is an event programmed, kill it 
     clearTimeout(eventId); 
     // and program the new one (replace the event) 
     eventId = setTimeout(fn); 
     // if passed the time no event was programmed, setTimeout is going to execute the function 
    } 
} 

// execute getData if no event is fired in a 1000ms interval (the user stopped typing) 
// getData is the same that you have 
var fn = handler(1000, getData); 

$("#filter").change(fn); 
関連する問題