JavaScript:関数の実行頻度を制限する

JavaScriptは驚くべき言語であり、予想外にクールなことをすることもあります。 私が最近遭遇した1つのパフォーマンスの問題に対する、わずかに非標準的なソリューションを紹介したいと思います。 警告:初心者向けではありません。



初期データ:特定のイベント(マウスの移動など)が発生すると、画面上の特定の要素を更新するリソース集約型の機能。

問題:関数を呼び出すイベントが短時間で頻繁に発生すると、インターフェースの速度が大幅に低下し始める可能性があります。 たとえば、イベントが数秒で1000回発生した場合、更新は同じです。 インターフェイスの場合、描画変更の電光石火の速度はそれほど重要ではないかもしれませんが、この場合に苦しむ全体的なパフォーマンスは非常に重要です。

タスク:関数を制限して、特定の期間に1回のみ実行されるようにします。 このような間隔が十分に短い場合、視覚的な遅延は目立たなくなりますが、呼び出し回数を数回減らすことができます。これにより、負荷が大幅に削減され、ブレーキがなくなります。



最初にいくつかの仮定を行いましょう。



  1. 関数は常に実行される必要はなく、選択的に実行されるため、特別な方法で選択可能なフラグ変数を設定および確認するフラグ変数が必要です。
  2. 関数が呼び出されても実行できない場合(指定された間隔が前回の実行から経過していない場合)、そのままにすることはできません。間隔が切れた後に実行する必要があります。最後の呼び出しが完了していない場合)。 これを行うには、そのような呼び出しについて話すフラグ変数が必要です。これは間隔の終わりにチェックされます。
  3. 連続していくつかの未実行の呼び出しがある場合は、最後の間隔だけを最後まで延期すれば十分です。 これを行うには、最後の関数呼び出しの引数を変数に保存する必要があります。
  4. 上記の方法で作業すると、制限後、関数は元のスコープと受け入れられた引数を保持する必要があります-当然です。




コードに移りましょう。 後で順番に分析します。



  var limitExecByInterval = function(fn、time){	
	 var lock、execOnUnlock、args;
	 return関数(){
		 args = arguments;
		 if(!lock){				
			 lock = true;
			 var scope = this;
			 setTimeout(関数(){
				 lock = false;
				 if(execOnUnlock){
					 args.callee.apply(scope、args);
					 execOnUnlock = false;
				 }
			 }、time);
			 return fn.apply(this、args);
		 } else execOnUnlock = true;
	 }
 } 




limitExecByInterval



は、入力関数とミリ秒単位の間隔を入力として受け取り、上記のように実行される変更された関数を返します。 (簡単にするため、 Function.prototype



メソッドでは作成しませんでしたが、可能です)。 使用例:



var myFunc = function(...) { ... }

var myLimitedFunc = limitExecByInterval(myFunc, 150);








必要に応じて、 Function.prototype



を使用して任意の関数のメソッドにすることができます。 これを行うには、最初の2行を次のように変更します。



  Function.prototype.limitExecByInterval = function(time){
	 var lock、execOnUnlock、args、fn = this;
	 ... 


その後、次のように呼び出すことができます。



var myLimitedFunc = myFunc.limitExecByInterval(150);







それでは、コードで何が起こるか見てみましょう。



最初に、必要な変数が宣言されます-返される関数の外側に注意してください-それらはすべての呼び出しに共通です。 リターン関数で:

  1. 呼び出し引数を保存します(仮定の条項3を参照)
  2. ロックフラグが設定されていない場合

    1. ロックフラグを設定します(アイテム1)
    2. 次のステップ(項目4)のために関数のスコープを保存します
    3. 次の間隔を取っておきます。

      • ロックフラグをクリアします(p。1)
      • 実行フラグが間隔の最後に設定されている場合(2節)、それを削除して、変更された機能全体を実行します。


    4. 指定された引数、同じスコープ、戻り値を使用して元の関数を実行します。 (4ページ)




動作するコードを使用した最も簡単な例次に示します。 (興味深い点:制限の使用の違いはFFとIEで明らかに見えますが、OperaとSafariでは両方のバージョンですべてが非常に高速です)。

彼が自分自身を明確にしたことを願っています。 :)事は複雑ですが、私は実際に実際の問題を解決するために実際に実際に助けました。 コメントの内容を理解し、誰がどのようなコメントになるかを理解してください。 :)



All Articles