web-dev-qa-db-fra.com

Modification de l'intervalle de SetInterval en cours d'exécution

J'ai écrit une fonction javascript qui utilise setInterval pour manipuler une chaîne tous les dixièmes de seconde pendant un certain nombre d'itérations.

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);
};

Au lieu de définir l’intervalle sur un nombre spécifique, j’aimerais le mettre à jour à chaque exécution, en fonction d’un compteur. Donc au lieu de:

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

Ce serait quelque chose comme:

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

Malheureusement, cela n'a pas fonctionné. Il semblait que "10 * counter" était égal à 0.

Alors, comment puis-je ajuster l'intervalle chaque fois que la fonction anonyme est exécutée?

136
Joe Di Stefano

Utilisez setTimeout() à la place. Le rappel sera alors responsable du déclenchement du prochain délai d'expiration, auquel cas vous pourrez augmenter ou autrement manipuler le minutage.

MODIFIER

Voici une fonction générique que vous pouvez utiliser pour appliquer un délai de décélération pour TOUT appel de fonction.

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);
81
Peter Bailey

Vous pouvez utiliser une fonction anonyme: 

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

MISE À JOUR: comme l'a suggéré A. Wolff, utilisez setTimeout pour éviter le besoin de clearInterval.

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

J'aime cette question - inspiré un petit objet de minuterie en moi:

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();
};

Exemple d'utilisation

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);
24
gnarf

J'ai eu la même question que l'affiche originale, l'a fait comme solution. Je ne sais pas à quel point c'est efficace ....

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()

    }
15
user28958

C'est ma façon de faire, j'utilise 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);
    }
};

Usage:

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

timer.set_interval(500);

timer.stop();
8
Atticweb

Un moyen beaucoup plus simple serait d’avoir une instruction if dans la fonction actualisée et un contrôle pour exécuter votre commande à des intervalles de temps réguliers. Dans l'exemple suivant, je lance une alerte toutes les 2 secondes et l'intervalle (intrv) peut être modifié de manière dynamique ...

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

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

La réponse simple est vous ne pouvez pas mettre à jour un intervalle de temporisateur déjà créé. (Il n'y a que deux fonctions setInterval/setTimer et clearInterval/clearTimer; vous ne pouvez donc la désactiver que si vous avez une timerId). Vous pouvez toutefois effectuer certaines solutions de contournement. Jetez un oeil à ce github repo .

3
vbarbarosh

Cela peut être lancé comme vous le souhaitez. timeout est la méthode que j'ai utilisée pour le garder au dessus de l'heure.

J'avais besoin de chaque heure pour commencer un bloc de code sur l'heure. Donc, cela commencerait au démarrage du serveur et exécuterait l’intervalle toutes les heures. Essentiellement, la première exécution consiste à commencer l'intervalle dans la même minute. Donc, dans une seconde après init, lancez immédiatement puis toutes les 5 secondes. 

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();

Alternativement, si vous vouliez que quelque chose se passe au début puis à jamais à un intervalle spécifique, vous pouvez simplement l'appeler en même temps que setInterval. Par exemple: 

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

Ici nous avons cette course la première fois et ensuite toutes les heures.

3
Dgerena

Je ne pouvais pas synchroniser et modifier la vitesse de mes setIntervals également et j'étais sur le point de poser une question. Mais je pense avoir trouvé un moyen. Cela devrait certainement être amélioré parce que je suis débutant. Donc, je serais heureux de lire vos commentaires/remarques à ce sujet.

<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>

Si vous souhaitez que les compteurs commencent à augmenter une fois la page chargée, insérez counter1() et counter2() dans foo() avant que countingSpeed soit appelé. Sinon, il faut speed millisecondes avant l'exécution . EDIT: Réponse plus courte.

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

Voici encore un autre moyen de créer un minuteur d’intervalle décélérant/accélérant. L'intervalle est multiplié par un facteur jusqu'à ce qu'une durée totale soit dépassée.

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();
}
0
jo_va

Je suis un débutant en javascript et je n'ai trouvé aucune aide dans les réponses précédentes (mais beaucoup de bonnes idées).
Ce morceau de code ci-dessous accélère (accélération> 1) ou décélère (accélération <1). J'espère que cela pourrait aider certaines personnes:

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);
}

Avec :

  • timer: valeur initiale de setInterval en ms (croissante ou décroissante)
  • refresh: le temps avant qu'une nouvelle valeur de timer soit calculée. C'est la longueur de l'étape
  • factor: écart entre l'ancienne et la prochaine valeur timer. C'est la step height
0
mquantin
(function variableInterval() {
    //whatever needs to be done
    interval *= 2; //deal with your interval
    setTimeout(variableInterval, interval);
    //whatever needs to be done
})();

ne peut pas être plus court

0
mikakun

Faire une nouvelle fonction:

// 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();
}
0
doshi smit