web-dev-qa-db-fra.com

Timing dans JS - plusieurs setIntervals s'exécutant en même temps et commençant en même temps?

Disons que j'ai une fonction:

myFunc = function(number) {
  console.log("Booyah! "+number);
}

Et je veux qu'il fonctionne sur un intervalle défini. On dirait que je devrais utiliser setInterval , hein!

Mais que se passe-t-il si je veux exécuter plusieurs intervalles de la même fonction, tous commençant en même temps?

setInterval(function(){
  myFunc(1);
}, 500);

setInterval(function(){
  myFunc(2);
}, 1000);

setInterval(function(){
  myFunc(3);
}, 2000);

Pour que le premier s'exécute exactement deux fois dans le temps, il faut que le second s'exécute une fois, et le même entre le deuxième et le troisième.

Comment vous assurez-vous qu'ils démarrent tous en même temps pour être synchronisés?

22
Joshua Soileau

Bonne question, mais dans JS, vous ne pouvez pas. Pour avoir plusieurs fonctions dans le même programme exécutées en même temps, vous avez besoin du multi-threading et de quelques compétences approfondies de synchronisation et de gestion des threads. JS est à filetage unique. setInterval n'exécute pas réellement la fonction après le délai, mais plutôt après le délai, elle ajoute la fonction à la pile d'événements à exécuter dès que le processeur peut y accéder. Si le proc est occupé par une autre opération, il faudra plus de temps que le délai pour s'exécuter réellement. Plusieurs intervalles/délais d'expiration ajoutent tous des appels à la même pile d'événements, ils s'exécutent donc tour à tour lorsque le proc est disponible.

23
JAAulde
function Timer(funct, delayMs, times)
{
  if(times==undefined)
  {
    times=-1;
  }
  if(delayMs==undefined)
  {
    delayMs=10;
  }
  this.funct=funct;
  var times=times;
  var timesCount=0;
  var ticks = (delayMs/10)|0;
  var count=0;
  Timer.instances.Push(this);

  this.tick = function()
  {
    if(count>=ticks)
    {
      this.funct();
      count=0;
      if(times>-1)
      {
        timesCount++;
        if(timesCount>=times)
        {
          this.stop();
        }
      }
    }
    count++; 
  };

  this.stop=function()
  {
    var index = Timer.instances.indexOf(this);
    Timer.instances.splice(index, 1);
  };
}

Timer.instances=[];

Timer.ontick=function()
{
  for(var i in Timer.instances)
  {
    Timer.instances[i].tick();
  }
};

window.setInterval(Timer.ontick, 10);

Et pour l'utiliser:

function onTick()
{
  window.alert('test');
}
function onTick2()
{
  window.alert('test2');
}
var timer = new Timer(onTick, 2000,-1);
var timer = new Timer(onTick2, 16000,-1);

Pour un nombre fini de graduations, remplacez le dernier paramètre par un entier positif pour nombre. J'ai utilisé -1 pour indiquer un fonctionnement continu.

Ignorez toute personne qui vous dit que vous ne pouvez pas. Vous pouvez le faire faire à peu près tout ce que vous aimez!

6
user5078091

JavaScript est un thread unique. Vous pouvez utiliser le travailleur Web html5 ou essayer d'utiliser récursivement setTimeout. Créez plusieurs fonctions en suivant cet exemple:

var interval = setTimeout(appendDateToBody, 5000);

function appendDateToBody() {
    document.body.appendChild(
        document.createTextNode(new Date() + " "));
    interval = setTimeout(appendDateToBody, 5000);
}

Lisez cet article:

http://weblogs.asp.net/bleroy/archive/2009/05/14/setinterval-is-moderately-evil.aspx

3
Alex Shilman

Vous pouvez faire quelque chose comme ça.

arr = Array();
arr[0] = "hi";
arr[1] = "bye";
setTimer0 = setInterval(function(id){
  console.log(arr[id])
},1000,(0));

setTimer1 = setInterval(function(id){
  console.log(arr[id]);
},500,(1));

J'espère que ça aide!

2
Bartuken