JavaScript 中的節流函式

Jagathish 2023年10月12日
JavaScript 中的節流函式

本教程介紹如何在 JavaScript 中為函式新增節流函式。

在 JavaScript 中新增節流限制

我們可以通過限流來限制某個資源在特定時限內被訪問的次數。

例如,我們將一個函式配置為在一分鐘內僅呼叫 10 次。當我們呼叫超過 10 次時,應該阻止執行。

為了實現節流,我們將維護以下資料:

  • 保持函式被呼叫的最大次數的變數。
  • 保持時間範圍的變數(如 1 分鐘)。
  • 用於維護上次呼叫該方法的時間的變數。
  • 用於維護在當前時間範圍內呼叫函式的次數的變數。

JavaScript 中的節流演算法

呼叫該函式時,我們將按照以下步驟進行操作:

  • 查詢當前時間與上次呼叫函式的時間之間的時間差。
    timeDiff = currentTime - lastInvokedTime
    
  • 如果時間差大於配置的 timeFrame,將函式在當前時間幀內呼叫的次數重置為 0
    if (timeDiff >= timeFrame) {
      numberOfTimesInvoked = 0;
    }
    
  • 檢查函式在當前時間範圍內被呼叫的次數是否小於或等於配置的函式可以被呼叫的次數。
    if (numberOfTimesInvoked < numOfTimesFnCanBeInvoked) {
      // invoke the function
    } else {
      // log fn cannot be invoked more than n times
    }
    
  • 在呼叫函式時,我們應該將函式呼叫的次數增加 1。此外,最後呼叫的時間應更新為當前時間。

程式碼示例:

class Throttle {
  constructor(timeFrame, numOfTimesFnCanBeInvoked, func) {
    this.lastInvokedTime = 0;
    this.numberOfTimesInvoked = 0;
    this.timeFrame = timeFrame;
    this.numOfTimesFnCanBeInvoked = numOfTimesFnCanBeInvoked;
    this.func = func;
  }
  call() {
    let currentTime = new Date();
    let timeDiff = currentTime - this.lastInvokedTime;
    if (timeDiff >= this.timeFrame) {
      this.numberOfTimesInvoked = 0;
    }
    if (this.numberOfTimesInvoked < this.numOfTimesFnCanBeInvoked) {
      this.func.apply(this, arguments);
      this.numberOfTimesInvoked++;
      this.lastInvokedTime = currentTime;
    } else {
      console.log(`Trying to call more than ${
          this.numOfTimesFnCanBeInvoked} times within ${this.timeFrame}ms`);
    }
  }
}

上面的程式碼將處理函式的限制。讓我們建立一個函式併為此新增限制。

function add(a,b){
  console.log(`${a} + ${b} = ${a+b}`);
}

let sum = new Throttle(2000, 2, add) // in 10 sec only two time this method can be called

sum.call(1,2);
sum.call(3,4);
sum.call(5,6); // this will not be executed

setTimeout(()=>{
	console.log("After 2000ms");
	sum.call(5,6); // this will be executed 
	sum.call(7,8);
}, 2000);

輸出

1 + 2 = 3
3 + 4 = 7
Trying to call more than 2 times within 2000ms

After 2000ms
5 + 6 = 11
7 + 8 = 15

在上面的程式碼中,

  • 我們建立了一個函式 add
  • 我們為 Throttle 類建立了一個新物件。將 add 函式配置為在 2 秒內僅呼叫兩次。
  • 我們在 2 秒內呼叫了 add 函式 3 次。對於前兩個函式呼叫,函式將被執行。但是對於第三次函式呼叫,該函式將不會被呼叫。
  • 我們使用 setTimeout 在 2 秒後呼叫 add 函式。這個時間段將是新的,這樣函式就會被執行。

相關文章 - JavaScript Function