Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Ограничение на количество вызовов функции за время < 10мс (https://javascript.ru/forum/misc/54500-ogranichenie-na-kolichestvo-vyzovov-funkcii-za-vremya-10ms.html)

Basil_JS 19.03.2015 18:57

Ограничение на количество вызовов функции за время < 10мс
 
Здравствуйте! Очень нужна помощь.

Есть функция, которая, так получилось, вызывается очень часто за короткий промежуток времени. Нужно сделать так, чтобы количество её вызовов не превышало 5 за 10мс.

Сама функция:
function game(i,j)
{
if (self.X[i] === self.X1[j] && (self.Y[i] === self.Y1[j] + 1 || self.Y[i] === self.Y1[j] - 1))
{
//console.log('Игра');
cell_game++;
}
else if (self.X[i] === self.X1[j] - 1 && (self.Y[i] === self.Y1[j] || self.Y[i] === self.Y1[j] + 1 || self.Y[i] === self.Y1[j] - 1))
{
//console.log('Игра');
cell_game++;
}
else if (self.X[i] === self.X1[j]+1 && (self.Y[i] === self.Y1[j] || self.Y[i] === self.Y1[j] + 1 || self.Y[i] === self.Y1[j] - 1 ))
{
//console.log('Игра');
cell_game++;
}
}

Благодарю заранее.

demoniqus 20.03.2015 12:00

Примерно так:
runsCounter = 0;
lastTime = (new Date()).getTime();
function game(){
	
	if ((new Date()).getTime() - lastTime <= 10) {
		++runsCounter;/*Увеличиваем счетчик исполнений*/
		if (runsCounter < 6) {
		/*Здесь ты можешь выполнять свой код*/
		}
	}
	else {
		/*Начался новый интервал времени, поэтому все переменные выставляем в дефолт*/
		lastTime = (new Date()).getTime();
		runsCounter = 0;
	}
}

Aetae 20.03.2015 14:38

demoniqus, неа. Если например 1 вызов будет на первой мс, затем 4 на десятой, потом 4 на первой и 1 на десятой, то получится 8 вызовов за 2 мс.) Тут надо хранить время последних четырёх вызовов и от него отталкиваться.

demoniqus 20.03.2015 15:03

Aetae, какая хитропопая трактовка))))))))))) Я о таком варианте не думал как-то...
Тогда примерно так:
nowIteration = 0;
iterationLimit = 5;
timeLimit = 10;
historyTimes = {};
for (var i = 0; i < iterationLimit; ++i) {
	historyTimes[i] = (new Date()).getTime();
}
function game(){
	var t = (new Date()).getTime();
	/*Следующая итерация является самой старой по отношению к текущей, поэтому сравниваем с ее временем*/
	nextIteration = nowIteration + 1;
	nextIteration >= iterationLimit && (nextIteration = 0);
	if (t - historyTimes[nextIteration] > timeLimit) {
		historyTimes[nowIteration] = t;
		nowIteration = nextIteration;
		
		/*Основной код процедуры*/
	}
}

Храним историю необходимого количества операций. При каждой попытке вызова требуемой функции сравниваем текущее время с самой ранней из всех записей в данной истории, индекс которой на единицу больше текущей итерации.
Если в первом случае временные отрезки исчислялись последовательно без наложения и действительно возникала та ситуация, которую ты описал, то во втором примере подобного уже не должно быть.

nerv_ 20.03.2015 16:19

уже придумано и отлажено

https://lodash.com/docs#debounce
https://lodash.com/docs#throttle

Aetae 20.03.2015 16:38

nerv_, прочитай внимательней условие.)

Яб написал примерно так:
game = limit(game, 5, 10)
function limit(func, count, time){
    var result, array = new Array(count);

    return function(){        
        if(time > new Date() - array[0]) return result; //возвращаем результат последнего вызова
        result = func.apply(this, arguments); //исполняем функцию в текущем контексте с нужными аргументами
        array.shift();     
        array.push(new Date());

        return result;
    }
}

рони 20.03.2015 20:10

:write: мысли вслух -- не более 3 кликов за 5 сек
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
</head>

<body>  <input name="" type="button" value="test" onclick="game(this)">
<script>
var counter = 3,
    time = 5000,
    temp = [],
    n = 0;

function game(obj) {
    temp.push((new Date()).getTime());
    var ok = limit(temp, time)
    obj.style.backgroundColor = ok ? "lime" : "red"
    n += +ok;
    obj.value = n;
}


function limit(arr, time) {
    var sum = 0;
    for (var i = arr.length - 1, a, b; a = arr[i--];) {
        b = arr[i];
        b && (sum += (a - b));
        sum > time && (arr.splice(0, i + 1))
    };
    var ok = sum > time || arr.length <= counter;
    !ok && arr.pop();
    return ok
}
</script>
</body>

</html>

nerv_ 20.03.2015 20:48

Цитата:

Сообщение от Aetae
nerv_, прочитай внимательней условие.)

я его читал и ссылки не просто так постил)
http://learn.javascript.ru/play/uUXAV


Часовой пояс GMT +3, время: 14:25.