2012-01-06 12 views
4

次のようなシナリオに直面しました。問題を解決するjQueryの組み込み方法があるのでしょうか? 。Javascriptでは、関数がすでに実行されている場合に関数の実行をキューに入れ、以前にキューに入れられたものをキャンセルします。

$(document).click(function() { 
    paintCanvas(); 
}); 

このコードの問題は、ユーザが画面上で迅速に連続して50回をクリックした場合は、paintCanvasに50回のコールでブラウザをオーバーロードしようとしているということです。

は、次のコードを想像してみてください。

paintCanvasが現在実行中で、新しいリクエストが作成された場合、paintCanvasが実行を終了するまで待機するように新しいリクエストをキューに入れたいとします。しかし同時に、すべての中間状態ではなく、マウスの最終状態のみを気にするので、以前にキューに入れられた呼び出しをpaintCanvasにドロップできます。

var _isExecuting, _isQueued; 

function paintCanvas() { 
    if (_isExecuting) { 
     if (!_isQueued) { 
      _isQueued = true; 
      setTimeout(function() { 
       _isQueued = false; 
       paintCanvas(); 
      }, 150); 
     } 
     return; 
    } 

    _isExecuting = true; 

    // ... code goes here 

    _isExecuting = false; 
}; 

This AJAX queue plugin基本的にこの機能を実装していますが、唯一のAJAXの面でそう:ここ

は、問題を解決し、いくつかのコードです。確かに、これはより一般的な方法で解決できる非常に一般的な問題ですか?

答えて

2

スロットル/デバウンス機能が必要なような音がします。

何私はjQueryのからの知っている方法で構築されているがあり、あなたは、しかし、これらのいずれかを使用することはできません。

http://benalman.com/projects/jquery-throttle-debounce-plugin/

@rkwがリンクを提供しますが

http://jsperf.com/jquery-throttle-methods

+1

Ext-JSには、ハンドラを設定するときに同じコンセプトが組み込まれていますが、Element.addListener( "click"、this、{buffer:150})のようなオプションを与えることができます。もう一度呼び出され、カウンタが再起動されます).http://docs.sencha.com/core/source/Observable.html#method-Ext.util.Observable-addListenerユーザーがjQueryについて質問したことは分かりますが、私は他のフレームワークにこれが組み込まれていることを言いたいだけです –

+1

他のjavascriptフレームワークがありますか? – cbp

+0

私は、jQueryには耐えられません:)私は手続き型コードの代わりにOOコードを好む。だからこそ私は完全にOOベースのExt-JSを使用しています。 –

3

mousemoveでこの問題を解決する必要はありません。これは、システムが既にそれを実行しているためです。 paintCanvasは実行中ですが、マウスが激しく動いていても数百のmousemoveイベントは生成されません。むしろ、次のイベントは、マウスの現在の位置であり、介在するすべてのマウスイベントの待ち行列ではありません。

このjsFiddle:http://jsfiddle.net/jfriend00/4ZuMn/を見てください。

あなたの望む速さで体の中でマウスを右下に振ります。その後、ペインからマウスを移動し、カウントがすぐに停止することを確認します。これ以上のマウスイベントはありません。マウスイベントを積み重ねることはありません。システムは、次のマウスイベントの準備ができているときはいつでも、マウスの最新の位置を取得します。個々のマウスの動きは、キューに入れられず、蓄積されません。マウスがより多くの位置を通過したとしても、マウスイベントのリストで、マウスイベントが多数存在しないことがわかります(たとえば、座標が不足しています)。これは、マウスがその位置にあるときにマウスイベントを起こす準備ができていないために位置がスキップされたためです。

さらに、javascriptはシングルスレッドなので、現在マウスイベントを処理している間は新しいマウスイベントを受け取ることはありません。あなたがすでに持っているものを処理し終えるまで、システムは新しいものを生成しません。だから、あなたは決して_isExecutingtrueとしてあなたのコードのjavascriptで見ることはありません。あなたは単にその小切手を必要としません。そして、あなたがそのチェックを必要とせず、決して真実ではないので、あなたのキューイングコードは実行されません。あなたはこのjsFiddleで、再入力されたmousemoveイベントを決して捕まえることができないことをここに見ることができます:http://jsfiddle.net/jfriend00/ngnUT/。 inActionフラグは、マウスをどれくらい速く動かすかにかかわらず、真であるとはみなされません。

+0

フェア作業例ですが、私はそれを説明するためだけの例だった、のMouseMoveとの関係ではなかったのではなく、あなたが潜在的にある複数のメソッドを実行している心配する必要がどのような状況平行。代わりにクリックを取る - ユーザーが50種類の異なるものをクリックするとどうなるか。メソッドを50回実行したくない場合は、最後のクリックに対してのみ実行します。私はこの例を反映するように更新しました。あなたが説明する理由のために私の特定の解決策はとにかくうまくいかないと思う。しかし、問題は残っている。 – cbp

+0

私は、ブラウザがmousemoveイベントをバッファリングするのは当然ですが、ブラウザよりもさらに長い時間バッファリングしたいと思うかもしれません。しかし、なぜ '_isExecuting'が不要なのかについてのあなたのコメントは死んでいます。 –

1

、私はいつもに好みますここにコードを表示してください。ここでは、あなたが欲しいものを行うような簡単なコードをいくつか紹介します。別の関数のバッファされたバージョンを返す関数。これは与えられたdelayのイベントの受信を停止するまで遅延し続けます。最後のイベントの後の遅延を待つ必要がない場合は、これを微調整することができます。あなたが最初にタイムアウトを設定し、その後の呼び出しをsetTimeoutにオフセットしたときには、追跡するだけです。

ここで十分http://jsfiddle.net/mendesjuan/qfFjZ/

function createBuffered(handler, delay) { 
    var timeoutId = null; 

    return function() { 
    var me = this; 
    if (timeoutId) { 
     window.clearTimeout(timeoutId); 
    } 
    timeoutId = setTimeout(function() { 
     handle.apply(me, arguments); 
     timeoutId = null; 
    }, delay); 
    } 
} 
関連する問題