2016-09-20 79 views
0

所以我試圖編寫一個油門函數,當被調用時,調用回調函數但是在給定的時間間隔內只能達到一定的極限次數。如果達到限制,回調將被推入隊列中,在初始時間間隔後調用回調。setTimeout()在油門函數中立即被調用

const throttle = (cb, interval, maxCalls) => { 
    let calls = 0; 
    const records = []; 
    let totalCalls = 0; 
    return (...rest) => { 
     if(calls < maxCalls) { 
      calls++; 
      records.push(Date.now()); 
      totalCalls++; 
      cb.apply(null, rest); 
      setTimeout(() => { 
      calls--; 
      }, interval); 
     } else { 
      //cb within setTimeout being invoked immediately here 
      setTimeout(() => { 
       calls++; 
       records.push(Date.now()); 
       totalCalls++; 
       cb.apply(null, rest); 
       //console.log(allotedTime: interval - (Date.now() - records[(totalCalls-1)-maxCalls])); 
      }, interval - (Date.now() - records[(totalCalls-1)-maxCalls])); 
     } 
    } 
} 

const meow = (start, ...args) => { 
    console.log(Date.now() - start, ...args); 
} 

const burp = throttle(meow.bind(this, Date.now()), 10000, 2); 

setTimeout(() => burp('burp'), 0); // expect 2-7 'burp' 
setTimeout(() => burp('burp'), 5000); // expect 5000 'burp' 
setTimeout(() => burp('burp'), 6000); // expect 10000 'burp' 
setTimeout(() => burp('burp'), 7000); // expect 15000 'burp' 

的主要問題是,由於某種原因,內封鎖其他,功能不等待setTimeout和被立即調用。語法看起來很好,所以我很難搞清楚它爲什麼被調用。這是後的輸出被稱爲:

setTimeout(() => burp('burp'), 0); //6 'burp' 
setTimeout(() => burp('burp'), 5000); //5001 'burp' 
setTimeout(() => burp('burp'), 6000) //6001 'burp' 
//allotedTime: 4005 
setTimeout(() => burp('burp'), 7000); //10008 'burp' 
//allotedTime: 4993 

你會發現,如果你用的結果來自行添加allotedTime上面,你會得到所需的日誌。謝謝參觀。

Link to repl

+0

我想知道爲什麼你應該在間隔時間調用函數時使用'setTimeout'。命名「節流閥」功能,如果它不壓制任何東西是奇怪的。 – zeroflagL

回答

0

不知道如果我完全理解這個問題,但基於您的期望, 的其他區間應爲:

interval - (Date.now() - records[totalCalls-maxCalls])) 

因爲totalCalls是增量一旦回調被調用。因此,要麼添加totalCalls++;作爲else塊的第一條語句(在setInterval()之前),或者不要期望值遞增(建議編號1)。

+0

將totalCalls ++移出setTimeout工作!非常感謝! – petertdinh