LeetCode JavaScript 30 Days Challenge – Day16 – 2676. Throttle

    LeetCode JavaScript 30 Days Challenge

    Given a function fn and a time in milliseconds t, return a throttled version of that function.

    給予一個函式 fn 和一個以毫秒為單位的時間 t,回傳節流函式。
    

    A throttled function is first called without delay and then, for a time interval of t milliseconds, can’t be executed but should store the latest function arguments provided to call fn with them after the end of the delay.

    節流函式在第一次無延遲的呼叫時,然後在 t 豪秒的時間間隔內無法執行,
    但應儲存最新的參數直到延遲結束後呼叫函式。
    

    For instance, t = 50ms, and the function was called at 30ms, 40ms, and 60ms. The first function call would block calling functions for the following t milliseconds. The second function call would save arguments, and the third call arguments should overwrite currently stored arguments from the second call because the second and third calls are called before 80ms. Once the delay has passed, the throttled function should be called with the latest arguments provided during the delay period, and it should also create another delay period of 80ms + t.

    例如,t = 50ms,函式在 30ms、40ms 和 60ms 時被呼叫,第一個函式呼叫將在接下來的 t ms 內阻止呼叫函式。
    第二個函式呼叫將保存參數,而第三個函式呼叫的參數應覆蓋第二個函式的參數,因為第二個和第三個呼叫是在 80ms之前。
    當延遲結束後,應該使用延遲期間提供的參數來呼叫節流函式,並應該創建另一個 80ms + t 的延遲時間。
    

    Example 1:

    Input: t = 100, calls = [{"t":20,"inputs":[1]}]
    Output: [{"t":20,"inputs":[1]}]
    

    Example 2:

    Input: t = 50, calls = [{"t":50,"inputs":[1]},{"t":75,"inputs":[2]}]
    Output: [{"t":50,"inputs":[1]},{"t":100,"inputs":[2]}]
    

    Example 3:

    Input: t = 70, calls = [{"t":50,"inputs":[1]},{"t":75,"inputs":[2]},{"t":90,"inputs":[8]},{"t": 140, "inputs":[5,7]},{"t": 300, "inputs": [9,4]}]
    Output: [{"t":50,"inputs":[1]},{"t":120,"inputs":[8]},{"t":190,"inputs":[5,7]},{"t":300,"inputs":[9,4]}]
    

    solution:
    節流函數 throttle 的宣告中,timeout 被初始化為 null,nextTimeToCallFn 被初始化為 0。
    第一次呼叫時,delay 的計算結果為 0,表示無需延遲立即執行。
    在後續的呼叫中,delay 的計算是基於下一次呼叫函數的時間減去當前時間。
    如果之前已經設置了計時器 timeout,則使用 clearTimeout(timeout) 清除計時器。
    如果沒有設置過計時器,則執行 setTimeout() 並更新 nextTimeToCallFn 變數的值,
    這樣可以確保在下一次執行 fn 前的延遲時間。

    Code 1: Throttle BigO(1)

    var throttle = function(fn, t) {
      let timeout = null;
      let nextTimeToCallFn = 0;
      return function(...args) {
        const delay = Math.max(0, nextTimeToCallFn - Date.now());
        clearTimeout(timeout);
        timeout = setTimeout(() => { 
          fn(...args);
          nextTimeToCallFn = Date.now() + t;
        }, delay);
      }
    };
    

    FlowChart:
    Example 1

    let start = Date.now();
    function log(...inputs) { 
      console.log([Date.now() - start, inputs ])
    }
    const dlog = throttle(log, 100);
    setTimeout(() => dlog(1), 20);
    //[{"t":20,"inputs":[1]}]
    

    Example 2

    let start = Date.now();
    function log(...inputs) { 
      console.log([Date.now() - start, inputs ])
    }
    const dlog = throttle(log, 50);
    setTimeout(() => dlog(1), 50);
    setTimeout(() => dlog(2), 100);
    //[{"t":50,"inputs":[1]},{"t":100,"inputs":[2]}]
    

    Example 3

    
    let start = Date.now();
    function log(...inputs) { 
      console.log([Date.now() - start, inputs ])
    }
    const dlog = throttle(log, 70);
    setTimeout(() => dlog(1), 50);
    setTimeout(() => dlog(2), 75);
    setTimeout(() => dlog(8), 90);
    setTimeout(() => dlog(5,7), 140);
    setTimeout(() => dlog(9,4), 300);
    //[{"t":50,"inputs":[1]},{"t":120,"inputs":[8]},{"t":190,"inputs":[5,7]},{"t":300,"inputs":[9,4]}]