2016-09-20 8 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