JavaScript Debounce&Throttle


前言
現在必要なものがあると仮定して、スライドイベントを監督し、フィードバックを実行します.タッチパネルやマウスでページをスライドさせると、一秒に数十回のscrollイベントが発生します.携帯電話などの携帯端末でページをスライドさせると、毎秒100回のscrollイベントが発生します.私たちのコールバック関数が複雑であれば、ページの性能が悪くなります.
問題を解決するための2つのツール:debounce、throttle、それらはいくつかの類似点があります.例えば、作用はすべて制御対象関数が一定期間に実行する回数です.しかし、より多くの違いがあります.debounceは前後2回のイベント間隔が一定時間を超えない場合、何回トリガしても一回のコールバック関数だけが実行されます.また、throttleは、安定した時間間隔での一回のコールバック関数の実行を保証することができます.しかし、はっきりさせるべきなのは、debounceであろうと、throttleであろうと、制御するのはすべてコールバック関数の実行であり、イベントの傍受ではない.
また、debounceとthrottleはただ一つの思想であり、多くの実現が可能であり、もちろん自分で実現することもできます.後文のコードは全部lodashのdebounceとthrottleに基づいています.
debounce
エレベーターが閉まります.エレベーターに乗る人がいると、エレベーターが閉まります.しばらくして(エレベーターがドアを完全に閉めるまでの間)、エレベーターは閉まります.またエレベーターに乗る人もいます.最後の人が入るまで、エレベーターは完全に閉まります.途中でエレベーターは一回だけ閉まりました.
このシーンはdebounceのリアルライフのモデルとも言える.コードレベルに戻る:
// debounce(callback, millisecond, options)
var onScroll = debounce(animation, 1000, { leading: true, trailing: false });

// right
$('#container').addEventListener('scroll', onScroll);

// wrong
$('#container').addEventListener('scroll', function(){
    debounce(callback, millisecond, options);
});
debounceは、3つのパラメータを受け取ります.制御する関数、2つのイベント間隔の最大ミリ秒数、および設定オブジェクトは、通常は直接イベント処理関数として返されます.詳細には、3番目のパラメータのOoptionsについて、このパラメータのデフォルト値は以下の通りです.
{ leading: false,  trailing: true }
leading:イベントがトリガされると、まず一回のコールバック関数を実行して、その後の呼び出しを制御します.このようにする利点は、イベントがトリガされると、フィードバックが実行され、より真実です.triling:まずコールバック関数を制御して、イベントのトリガ間隔が設定時間を超えるまで、再度コールバック関数を呼び出して、上のエレベーターが閉まっている例のように、両方がtrueである場合、一回の制御過程でコールバックは二回行われます.両者が同時にfalseの場合、コールバックは実行されません.
よくあるアプリケーションシーン:ドラッグウィンドウのサイズ、リアルタイム検証input
スロットル
debounceに比べて、throttleは特殊化されたsetIntervalのようです.つまり、throttleが包装した関数は一定の時間間隔で実行されます.これはイベントのトリガと関係があり、set Intervalのように手動でキャンセルする必要がないと違います.
throttle(callback, millisecond)
したがって、throttleは継続的に実行する必要がありますが、実行回数を制御して性能を最適化する関数が必要です.例えば、スライドする時にスライドのデータ(scrollTopなど)によって、ある要素のスタイルを変え続けます.この場合、間隔を長く設定すると流れが悪くなり、短すぎると最適化の効果が得られません.一般に16 msとすると、フレームレートは60 fpsとなり、良好な視覚効果を維持することができる.ここまで言うと、ブラウザの原生API request Animation Frameと言わざるを得ません.
ざっと言うと、request Animation Frameは相当です.
throttle(callback, 16);
rAFの利点は、元のAPIで安定していることです.もちろん多くの欠点もあります.例えば手動での起動とキャンセルが必要です.ブラウザtabがactiveではない時は実行されません.IE 9はサポートされていません
caveat
  • debounce、throttleは多くの実現があり、自分で実現することもできますが、直接にloadshまたはundersscoreを使うことを勧めます.専門的なツールバンクは私たち自身より多くのことを考えています.心配しないでください.二つの関数を使うためにlodashライブラリ全体を導入する問題です.
  • は、できるだけdebounceまたはthrottleが生成した関数を直接イベントハンドラ関数として使用し、このようなエラーのコードが書かれないようにする:
    $('#container').addEventListener('scroll', function(){
        //          ,     ,              
       debounce(callback, millisecond, options);
    });
    
  • 変数を使ってdebounceまたはthrottleの値を保存した後、キャンセルの方法を呼び出すことができます.setTimeoutのように:
    onScroll = debounce(animation, 1000, { leading: true,             
    trailing: false });
    
    $('#container').addEventListener('scroll', onScroll);
    
    onScroll.cancel();
    
    参照文章:Debouncing and Throttling Explined Through Examples