Изменение интервала SetInterval во время его выполнения

Я написал функцию javascript, которая использует setInterval для управления строкой каждую десятую секунды для определенного количества итераций.

function timer() {
    var section = document.getElementById('txt').value;
    var len = section.length;
    var rands = new Array();

    for (i=0; i<len; i++) {
        rands.push(Math.floor(Math.random()*len));
    };

    var counter = 0
    var interval = setInterval(function() {
        var letters = section.split('');
        for (j=0; j < len; j++) {
            if (counter < rands[j]) {
                letters[j] = Math.floor(Math.random()*9);
            };
        };
        document.getElementById('txt').value = letters.join('');
        counter++

        if (counter > rands.max()) {
            clearInterval(interval);
        }
    }, 100);
};

Вместо того, чтобы иметь интервал, заданный для определенного числа, я хотел бы обновлять его каждый раз, когда он запускается, на основе счетчика. Поэтому вместо:

var interval = setInterval(function() { ... }, 100);

Это будет что-то вроде:

var interval = setInterval(function() { ... }, 10*counter);

К сожалению, это не сработало. Казалось, что "10 * counter" равен 0.

Итак, как я могу отрегулировать интервал при каждом запуске анонимной функции?

Ответ 1

Используйте setTimeout() вместо этого. Затем обратный вызов будет отвечать за запуск следующего таймаута, после чего вы можете увеличить или иным образом манипулировать синхронизацией.

ИЗМЕНИТЬ

Вот общая функция, которую вы можете использовать для применения "замедляющего" тайм-аута для любого вызова функции.

function setDeceleratingTimeout(callback, factor, times)
{
    var internalCallback = function(tick, counter) {
        return function() {
            if (--tick >= 0) {
                window.setTimeout(internalCallback, ++counter * factor);
                callback();
            }
        }
    }(times, 0);

    window.setTimeout(internalCallback, factor);
};

// console.log() requires firebug    
setDeceleratingTimeout(function(){ console.log('hi'); }, 10, 10);
setDeceleratingTimeout(function(){ console.log('bye'); }, 100, 10);

Ответ 2

Вы можете использовать анонимную функцию:

var counter = 10;
var myFunction = function(){
    clearInterval(interval);
    counter *= 10;
    interval = setInterval(myFunction, counter);
}
var interval = setInterval(myFunction, counter);

ОБНОВЛЕНИЕ: Как предложил А. Вольф, используйте setTimeout, чтобы избежать необходимости clearInterval.

var counter = 10;
var myFunction = function() {
    counter *= 10;
    setTimeout(myFunction, counter);
}
setTimeout(myFunction, counter);

Ответ 3

Мне нравится этот вопрос - вдохновил небольшой объект таймера во мне:

window.setVariableInterval = function(callbackFunc, timing) {
  var variableInterval = {
    interval: timing,
    callback: callbackFunc,
    stopped: false,
    runLoop: function() {
      if (variableInterval.stopped) return;
      var result = variableInterval.callback.call(variableInterval);
      if (typeof result == 'number')
      {
        if (result === 0) return;
        variableInterval.interval = result;
      }
      variableInterval.loop();
    },
    stop: function() {
      this.stopped = true;
      window.clearTimeout(this.timeout);
    },
    start: function() {
      this.stopped = false;
      return this.loop();
    },
    loop: function() {
      this.timeout = window.setTimeout(this.runLoop, this.interval);
      return this;
    }
  };

  return variableInterval.start();
};

Пример использования

var vi = setVariableInterval(function() {
  // this is the variableInterval - so we can change/get the interval here:
  var interval = this.interval;

  // print it for the hell of it
  console.log(interval);

  // we can stop ourselves.
  if (interval>4000) this.stop();

  // we could return a new interval after doing something
  return interval + 100;
}, 100);  

// we can change the interval down here too
setTimeout(function() {
  vi.interval = 3500;
}, 1000);

// or tell it to start back up in a minute
setTimeout(function() {
  vi.interval = 100;
  vi.start();
}, 60000);

Ответ 4

У меня был тот же вопрос, что и исходный плакат, сделанный в качестве решения. Не уверен, насколько это эффективно.

interval = 5000; // initial condition
var run = setInterval(request , interval); // start setInterval as "run"

    function request() { 

        console.log(interval); // firebug or chrome log
        clearInterval(run); // stop the setInterval()

         // dynamically change the run interval
        if(interval>200 ){
          interval = interval*.8;
        }else{
          interval = interval*1.2;
        }

        run = setInterval(request, interval); // start the setInterval()

    }

Ответ 5

Это мой способ сделать это, я использую setTimeout:

var timer = {
    running: false,
    iv: 5000,
    timeout: false,
    cb : function(){},
    start : function(cb,iv){
        var elm = this;
        clearInterval(this.timeout);
        this.running = true;
        if(cb) this.cb = cb;
        if(iv) this.iv = iv;
        this.timeout = setTimeout(function(){elm.execute(elm)}, this.iv);
    },
    execute : function(e){
        if(!e.running) return false;
        e.cb();
        e.start();
    },
    stop : function(){
        this.running = false;
    },
    set_interval : function(iv){
        clearInterval(this.timeout);
        this.start(false, iv);
    }
};

Использование:

timer.start(function(){
    console.debug('go');
}, 2000);

timer.set_interval(500);

timer.stop();

Ответ 6

Гораздо проще было бы иметь оператор if в обновленной функции и элемент управления для выполнения вашей команды с регулярными временными интервалами. В следующем примере я запускаю предупреждение каждые 2 секунды, и интервал (intrv) можно динамически изменять...

var i=1;
var intrv=2; // << control this variable

var refreshId = setInterval(function() {
  if(!(i%intrv)) {
    alert('run!');
  }
  i++;
}, 1000);

Ответ 7

Простой ответ , вы не можете обновить интервал уже созданного таймера. (Существует только две функции setInterval/setTimer и clearInterval/clearTimer, поэтому, имея timerId, вы можете деактивировать ее.) Но вы можете сделать некоторые обходные пути. Посмотрите это github repo.

Ответ 8

Это может быть инициировано, но вы хотите. timeout - это метод, который я использовал, чтобы держать его в верхней части часа.

У меня была потребность в каждом часе, чтобы начать блок кода в час. Таким образом, это началось бы при запуске сервера и выполняло бы интервал почасово. В основном начальный прогон - начать интервал в пределах одной минуты. Таким образом, через секунду от init запускайте сразу же каждые 5 секунд.

var interval = 1000;
var timing =function(){
    var timer = setInterval(function(){
        console.log(interval);
        if(interval == 1000){ /*interval you dont want anymore or increment/decrement */
            interval = 3600000; /* Increment you do want for timer */
            clearInterval(timer);
            timing();
        }
    },interval);
}
timing();

Альтернативно, если вы хотите, чтобы что-то произошло в начале, а затем навсегда с определенным интервалом, вы можете просто вызвать его одновременно с setInterval. Например:

var this = function(){
 //do
}
setInterval(function(){
  this()
},3600000)
this()

Здесь мы запускаем этот первый и каждый час.

Ответ 9

Я не мог синхронизировать и изменять скорость моих setIntervals тоже, и я собирался опубликовать вопрос. Но я думаю, что нашел способ. Это, безусловно, должно быть улучшено, потому что я новичок. Поэтому я с удовольствием прочитал бы ваши комментарии/замечания по этому поводу.

<body onload="foo()">
<div id="count1">0</div>
<div id="count2">2nd counter is stopped</div>
<button onclick="speed0()">pause</button>
<button onclick="speedx(1)">normal speed</button>
<button onclick="speedx(2)">speed x2</button>
<button onclick="speedx(4)">speed x4</button>
<button onclick="startTimer2()">Start second timer</button>
</body>
<script>
var count1 = 0,
    count2 = 0,
    greenlight = new Boolean(0), //blocks 2nd counter
    speed = 1000,   //1second
    countingSpeed;
function foo(){
    countingSpeed = setInterval(function(){
        counter1();
        counter2();
    },speed);
}
function counter1(){
    count1++;
    document.getElementById("count1").innerHTML=count1;
}
function counter2(){
    if (greenlight != false) {
        count2++;
        document.getElementById("count2").innerHTML=count2;
    }
}
function startTimer2(){
    //while the button hasn't been clicked, greenlight boolean is false
    //thus, the 2nd timer is blocked
    greenlight = true;
    counter2();
    //counter2() is greenlighted
}

//these functions modify the speed of the counters
function speed0(){
    clearInterval(countingSpeed);
}
function speedx(a){
    clearInterval(countingSpeed);
    speed=1000/a;
    foo();
}
</script>

Если вы хотите, чтобы счетчики начали увеличиваться после загрузки страницы, поместите counter1() и counter2() в foo() до вызова countingSpeed. В противном случае перед исполнением требуется speed миллисекунд. EDIT: более короткий ответ.

Ответ 10

var counter = 15;
var interval = setTimeout(function(){
    // your interval code here
    window.counter = dynamicValue;
    interval();
}, counter);

Ответ 11

Я новичок в javascript и не нашел никакой помощи в предыдущих ответах (но много хороших идей).
Эта часть кода ниже ускоряется (ускорение > 1) или замедляется (ускорение < 1). Надеюсь, это может помочь некоторым людям:

function accelerate(yourfunction, timer, refresh, acceleration) {
    var new_timer = timer / acceleration;
    var refresh_init = refresh;//save this user defined value
    if (refresh < new_timer ){//avoid reseting the interval before it has produced anything.
        refresh = new_timer + 1 ;
    };
    var lastInter = setInterval(yourfunction, new_timer);
    console.log("timer:", new_timer);
    function stopLastInter() {
        clearInterval(lastInter);
        accelerate(yourfunction, new_timer, refresh_init, acceleration);
        console.log("refresh:", refresh);
    };
    setTimeout(stopLastInter, refresh);
}

С помощью:

  • timer: начальное значение setInterval в мс (увеличение или уменьшение)
  • refresh: время, когда вычисляется новое значение timer. Это шаг длины
  • factor: разрыв между старым и следующим значением timer. Это высота шага

Ответ 12

(function variableInterval() {
    //whatever needs to be done
    interval *= 2; //deal with your interval
    setTimeout(variableInterval, interval);
    //whatever needs to be done
})();

не может стать короче

Ответ 13

Сделайте новую функцию:

// set Time interval
$("3000,18000").Multitimeout();

jQuery.fn.extend({
    Multitimeout: function () {
        var res = this.selector.split(",");
        $.each(res, function (index, val) { setTimeout(function () { 
            //...Call function
            temp();
        }, val); });
        return true;
    }
});

function temp()
{
    alert();
}

Ответ 14

Вот еще один способ создать таймер замедления/ускорения. Интервал умножается на коэффициент, пока не будет превышено общее время.

function setChangingInterval(callback, startInterval, factor, totalTime) {
    let remainingTime = totalTime;
    let interval = startInterval;

    const internalTimer = () => {
        remainingTime -= interval ;
        interval *= factor;
        if (remainingTime >= 0) {
            setTimeout(internalTimer, interval);
            callback();
        }
    };
    internalTimer();
}