2016-04-11 16 views
0

は現在、私は、resizeイベントをリッスンWindowオブジェクトにハンドラを持ってサイズを変更します。 doSomething()が1秒間に1回しか呼び出されず、それ以上頻繁に呼び出されないようにするには、doSomething()が1秒間呼び出されていないときにのみ呼び出されるようにしてください。Javascriptのデバウンスおよびスロットリングは

誰も私に平易なJavaScriptで比較的簡単な実装を提供できますか?

私は、ある時間間隔で機能が発火する割合を制限することについて理解しています。デバウンスとは、一定時間が経過するまで機能が呼び出されないようにすることです。

何か助けていただければ幸いです。ありがとう。

+0

概念を説明することを求めているのですか、これを実際的な目的で行う必要がありますか? – Dellirium

+0

私の学習目的のために、私は概念をかなり理解していますが、まだコードを書くのには十分ではありません。 – fittaoee

答えて

0

Here you go, fiddle exmple:

function doSomething(timer) { 
    timer = timer || 1000; 
    var alreadyFired; 
    var timerID = null; 
    var interruptCounter = -100; 
    var fireLimit = 5; 
    var fired = 0; 

    function Debounce() { //Old way, how I understood you inititally 
    if (alreadyFired != true) { 
     alreadyFired = true; 
     //Do stuff 
     console.log("fired"); 
     setTimeout(function() { 
     alreadyFired = false; 
     }, 1000); // Debouncing on 1 second 
    } 
    } 

    function ConstantFiring(firstIndicator) { // New way, as per comments. 
    //Do stuff 
    if (firstIndicator === true) { 
     console.log("fired for the 1st time"); 
    } else { 
     console.log("Firing constantly every " + timer/1000 + " seconds."); 
    } 
    } 

    function Throttle() { 
    if (fired < fireLimit) { 
     fired++; 
     //Do Stuff 
     console.log(fired); 
     setTimeout(function() { 
     fired--; 
     }, 3000); //Throttling on 5 fires per 3 seconds 
    } 
    } 

    function InterruptTimer() { 
    if (interruptCounter === -100) { 
     //This runs only the 1st time window is resized, if you leave this 
     //part out, the function will only fire 3 seconds AFTER the first 
     //event fired and then consistantly unless the event occured in 
     //last 3 seconds. 
     interruptCounter = 0; 
     ConstantFiring(true); 
    } 
    if (interruptCounter <= 0) { 
     interruptCounter++; 
     clearInterval(timerID); 
     timerID = null; 
     setTimeout(function() { 
     interruptCounter--; 
     if (interruptCounter <= 0 && timerID == null) { 
      timerID = setInterval(ConstantFiring, timer); 
     } 
     }, 3000); // Interrupt timer 
    } 
    } 

    //Change the following line to use a different function to test. 
    var realFunction = InterruptTimer; 
    return realFunction; 
} 

window.onresize = doSomething(768); //Add a parameter representing a 
            //period for the function timer (in milisec) 
            //This is very optional, you can also hardcode 
            // it into the doSomething fucntion in case 
            // you want to add some other event.[parameter]. 

EDIT:も「適切なコーディング」から指標として、単純なグローバル変数を使用すると、はるかに簡単な解決策、それほど混乱が、あまり「クリーン」であることを追加したいと思いますビューのタイプ。あなたがそうするならば、閉鎖に対処する必要はありません。

EDIT2:コメントと希望の動作を反映するようにコードとリンクを更新しました。

+0

ありがとうございます。また、私は最後の行で "= doSomething"ではなく "doSomething()"を書くべきなのかどうか疑問に思っています。イベントハンドラをアタッチするときに、カッコが必要でないことがあります。しかし、彼らはここで必要と思われる。 – fittaoee

+0

これは、解雇したい関数への参照を返すためです。 'doSomething()'はここで呼び出される関数ではなく、返される関数です。基本的には、あなたが 'doSomething()();と考えるものと同等です。それは難しいことです! :Pこれは、イベントをトリガするたびに 'doSomething'を起動したくないからです。代わりに、イベントが発生するたびに関数を返すためにハンドラに「アタッチ」された初期関数が必要です。 – Dellirium

+0

言い換えれば、私はこれを混乱させるかもしれないと思っていたので、明確にするために言います。バインド時に、doSomethingを呼び出して結果を返すようにしたいので、 "()"を使用します。あなたがそれを放置すると、あなたがサイズを変更するたびに、あなたはそれを望んでいません。あなたは一度だけdoSometingを発射し、それを返すことができます。イベントハンドラ。それを少しクリアすることを願っています。 – Dellirium