setTimeout ou setInterval?

autant que je puisse dire, ces deux morceaux de javascript se comportent de la même manière:

Option A:

function myTimeoutFunction()
{
    doStuff();
    setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

Option B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

y a-t-il une différence entre l'utilisation de setTimeout et setInterval ?

692
demandé sur Tiny Giant 2009-04-08 17:11:01

19 réponses

ils essaient essentiellement de faire la même chose, mais l'approche setInterval sera plus précise que l'approche setTimeout , puisque setTimeout attend 1000ms, exécute la fonction et puis fixe un autre délai. Si la période d'attente est en fait un peu plus de 1000ms (ou beaucoup plus si votre fonction prend du temps pour s'exécuter).

bien qu'on puisse penser que setInterval va exécuter exactement tous les 1000ms, il est important de noter ce setInterval retardera aussi, puisque JavaScript n'est pas un langage multi-threadé, ce qui signifie que - s'il y a d'autres parties du script en cours d'exécution - l'intervalle devra attendre que cela se termine.

Dans ce Violon , vous pouvez clairement voir que le délai d'attente de prendre du retard, alors que l'intervalle est presque tout le temps à près de 1 appel/seconde (dont le script est en train de faire). Si vous changez la variable de vitesse en haut en quelque chose de petit comme 20 (ce qui signifie qu'il va essayer de courir 50 fois par seconde), l'intervalle ne sera jamais tout à fait atteint une moyenne de 50 itérations par seconde.

le retard est presque toujours négligeable, mais si vous programmez quelque chose de vraiment précis, vous devriez aller pour un self-adjusting timer (qui est essentiellement un timeout-basé sur la minuterie qui s'ajuste constamment pour le retard qu'il est créé)

607
répondu David Snabel-Caunt 2016-11-16 22:58:55

y a-t-il une différence?

Oui. Un Timeout exécute un certain temps après que setTimeout() est appelé; un intervalle exécute un certain temps après que l'intervalle précédent a été lancé.

vous remarquerez la différence si votre fonction doStuff() prend un certain temps à exécuter. Par exemple, si nous représentons un appel à setTimeout / setInterval avec . , un tir de l'intervalle de temps avec * et l'exécution de code JavaScript avec [-----] , les délais ressemblent à:

Timeout:

.    *  .    *  .    *  .    *  .
     [--]    [--]    [--]    [--]

Interval:

.    *    *    *    *    *    *
     [--] [--] [--] [--] [--] [--]

la complication suivante est si un intervalle se déclenche alors que JavaScript est déjà occupé à faire quelque chose (comme gérer un intervalle précédent). Dans ce cas, l'intervalle est mémorisé, et se produit dès que le gestionnaire précédent termine et renvoie le contrôle au navigateur. Ainsi par exemple pour un processus de doStuff() qui est parfois court ([ - ]) et parfois long ([-----]):

.    *    *    •    *    •    *    *
     [-]  [-----][-][-----][-][-]  [-]
"151970920 • * représente un tir d'intervalle qui n'a pas pu exécuter son code immédiatement, et a été fait en attente à la place.

alors les intervalles essayent de " rattraper’ pour revenir à l'horaire. Mais, ils ne font pas la queue l'un sur l'autre: il ne peut y avoir qu'une exécution en attente par intervalle. (S'ils faisaient tous la queue, le navigateur se retrouverait avec une liste sans cesse croissante d'exécutions en suspens!)

.    *    •    •    x    •    •    x
     [------][------][------][------]

x représente un tir d'intervalle qui ne pouvait pas être exécuté OU être fait en attente, donc à la place a été écarté.

si votre fonction de doStuff() prend habituellement plus de temps à exécuter que l'intervalle qui est défini pour elle, le navigateur va manger 100% CPU essayant de le servir, et peut devenir moins réactif.

Qu'utilisez-vous et pourquoi?

temps D'arrêt enchaîné donne un créneau de temps libre garanti au navigateur; intervalle essaie de s'assurer que la fonction qu'il exécute se rapproche le plus possible de ses heures programmées, au détriment de la disponibilité de L'interface utilisateur du navigateur.

je considérerais un intervalle pour les animations uniques que je voulais être aussi lisse que possible, tandis que les temps morts enchaînés sont plus polis pour les animations en cours qui auraient lieu tout le temps pendant que la page est chargée. Pour des utilisations moins exigeantes (comme un tir trivial updater toutes les 30 secondes ou quelque chose comme ça), vous pouvez utiliser l'un ou l'autre en toute sécurité.

en termes de compatibilité de navigateur, setTimeout est antérieur à setInterval, mais tous les navigateurs que vous rencontrerez aujourd'hui prennent en charge les deux. Le dernier traînard pendant de nombreuses années était IE Mobile à WinMo <6,5, mais espérons que cela aussi est maintenant derrière nous.

632
répondu bobince 2013-06-26 10:22:49

setInterval ()

setInterval() est une méthode d'exécution de code basée sur un intervalle de temps qui a la capacité native d'exécuter à répétition un script spécifié lorsque l'intervalle est atteint. Il devrait et non être imbriqué dans sa fonction de rappel par l'auteur du script pour le faire boucle, puisqu'il boucles par défaut . Il va continuer à tirer à l'intervalle sauf si vous appelez clearInterval() .

si vous voulez un code boucle pour les animations ou sur une horloge, utilisez setInterval() .

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setInterval(doStuff, 5000);

setTimeout ()

setTimeout() est une méthode d'exécution de code basée sur le temps qui exécutera un script seulement une fois lorsque l'intervalle est atteint. Il répétera et non à moins que vous ne l'ameniez à boucler le script en imitant l'objet setTimeout() à l'intérieur de la fonction qu'il appelle à exécuter. S'il est réglé sur boucle, il continuera à tirer à l'intervalle à moins que vous n'appeliez clearTimeout() .

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setTimeout(doStuff, 5000);

si vous voulez que quelque chose arrive une fois après une période de temps déterminée, utilisez setTimeout() . C'est parce qu'elle n'exécute qu'une seule fois lorsque l'intervalle de temps spécifié est atteint.

83
répondu Haris 2014-06-04 17:38:20

le setInterval rend plus facile d'annuler l'exécution future de votre code. Si vous utilisez setTimeout, vous devez garder une trace de l'identifiant de la minuterie au cas où vous souhaiteriez l'annuler plus tard.

var timerId = null;
function myTimeoutFunction()
{
    doStuff();
    timerId = setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

// later on...
clearTimeout(timerId);

versus

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
var timerId = setInterval(myTimeoutFunction, 1000);

// later on...
clearInterval(timerId);
41
répondu Kamiel Wanrooij 2009-04-09 07:48:21

je trouve la méthode setTimeout plus facile à utiliser si vous voulez annuler le délai:

function myTimeoutFunction() {
   doStuff();
   if (stillrunning) {
      setTimeout(myTimeoutFunction, 1000);
   }
}

myTimeoutFunction();

aussi, si quelque chose tourne mal dans la fonction il cessera de répéter l'erreur à la première fois, au lieu de répéter l'erreur à chaque seconde.

20
répondu Guffa 2009-04-08 14:20:02

la différence réside dans leurs objectifs.

setInterval()
   -> executes a function, over and over again, at specified time intervals  

setTimeout()
   -> executes a function, once, after waiting a specified number of milliseconds

c'est aussi simple que ça

plus de détails ici http://javascript.info/tutorial/settimeout-setinterval

14
répondu kmario23 2014-06-03 11:33:42

lorsque vous exécutez une fonction à l'intérieur de setInterval, qui fonctionne plus longtemps que timeout-> le navigateur sera bloqué.



- E. g., doStuff() prend 1500 sec. à exécuter le et vous n': setInterval(doStuff, 1000);

1) Navigateur run doStuff() qui prend 1,5 sec. pour être exécuté;

2) Après ~1 seconde il essaie de courir doStuff() de nouveau. Mais le précédent doStuff () est toujours exécuté-> donc le navigateur ajoute cette course à la file d'attente (pour exécuter après que la première est terminée).

3,4,..) Le même ajout à la file d'exécution pour les itérations suivantes, mais doStuff() de la précédente sont toujours en cours...

comme résultat - le navigateur est bloqué.



Pour empêcher ce comportement, la meilleure façon est d'exécuter setTimeout à l'intérieur de setTimeout pour émuler setInterval .

pour corriger les temps morts entre les appels setTimeout, vous pouvez utiliser alternative autocorrectrice à la technique setInterval de JavaScript.

11
répondu Serg Hospodarets 2014-04-26 17:42:53

j'utilise setTimeout.

apparemment la différence est que setTimeout appelle la méthode une fois, setInterval l'appelle à répétition.

voici un bon article expliquant la différence: tutoriel: programmeurs JavaScript avec setTimeout et setInterval

7
répondu Bravax 2009-04-08 13:15:52

cet article dit que vous devez éviter setInterval si possible, d'autant plus que vous pouvez répliquer son comportement avec setTimeout et obtenir quelques avantages supplémentaires le long du chemin.

5
répondu John Sheehan 2009-06-03 23:43:32

j'ai fait le test simple de setInterval(func, milisec) , parce que j'étais curieux de savoir ce qui se passe quand la consommation de temps de fonction est plus grande que la durée d'intervalle.

setInterval sera généralement planification de l'itération suivante, juste après le démarrer de l'itération précédente, sauf si la fonction est toujours en cours . Si c'est le cas, setInterval attendra, jusqu'à la fin de la fonction. Dès qu'il arrive, la fonction est immédiatement tiré à nouveau - il n'y a pas d'attente pour la prochaine itération selon le calendrier (comme ce serait dans des conditions sans fonction de dépassement de temps). Il n'y a pas non plus de situation avec des itérations parallèles en cours.

j'ai testé ça sur Chrome v23. J'espère qu'il est déterministe de la mise en œuvre sur tous les navigateurs modernes.

window.setInterval(function(start) {
    console.log('fired: ' + (new Date().getTime() - start));
    wait();
  }, 1000, new Date().getTime());

sortie Console:

fired: 1000    + ~2500 ajax call -.
fired: 3522    <------------------'
fired: 6032
fired: 8540
fired: 11048

la fonction wait n'est qu'un fil helper de blocage-appel ajax synchrone qui prend exactement 2500 millisecondes de traitement du côté du serveur:

function wait() {
    $.ajax({
        url: "...",
        async: false
    });
}
5
répondu jwaliszko 2012-11-25 23:38:44

setInterval et setTimeout renvoient tous deux un identifiant de minuterie que vous pouvez utiliser pour annuler l'exécution, c'est-à-dire avant que les timeouts ne soient déclenchés. Pour annuler vous appelez soit clearInterval ou clearTimeout comme ceci:

var timeoutId = setTimeout(someFunction, 1000);
clearTimeout(timeoutId);
var intervalId = setInterval(someFunction, 1000),
clearInterval(intervalId);

de plus, les temps morts sont automatiquement annulés lorsque vous quittez la page ou fermez la fenêtre du navigateur.

3
répondu Helgi 2009-04-08 14:47:06

pour le Regarder un peu différemment: setInterval assure qu'un code est exécuté à chaque intervalle donné (i.e. 1000ms, ou combien vous spécifiez) tandis que setTimeout définit le temps qu'il "attend" qu'il exécute le code. Et comme il faut des millisecondes supplémentaires pour exécuter le code, il s'additionne à 1000ms et ainsi, setTimeout court à nouveau à des temps inexacts (plus de 1000ms).

par exemple, les timers / countdowns ne sont pas faits avec setTimeout, ils sont faits avec setInterval, pour s'assurer qu'il ne ne pas retarder et le code fonctionne à l'intervalle exact donné.

3
répondu CatalinBerta 2017-08-17 08:39:25

bien, setTimeout est mieux dans une situation, comme je viens de l'apprendre. J'utilise toujours setInterval, que j'ai laissé courir en arrière-plan pendant plus d'une demi-heure. Quand je suis revenu à cet onglet, le diaporama (sur lequel le code était utilisé) changeait très rapidement, au lieu de toutes les 5 secondes qu'il aurait dû avoir. Il se produit en fait à nouveau que je le tester plus et si c'est la faute du navigateur ou non n'est pas important, parce que avec setTimeout que la situation est complètement impossible.

2
répondu Nino 2011-10-18 16:48:42

la différence est évidente en console:

enter image description here

2
répondu testCoder 2014-01-04 21:02:31

vous pouvez valider vous-même la réponse de bobince lorsque vous utilisez le javascript suivant ou cochez cette case JSFiddle

<div id="timeout"></div>
<div id="interval"></div>

var timeout = 0;
var interval = 0;

function doTimeout(){
    $('#timeout').html(timeout);
    timeout++;
    setTimeout(doTimeout, 1);
}

function doInterval(){
    $('#interval').html(interval);
    interval++;
}

$(function(){
    doTimeout();
    doInterval();
    setInterval(doInterval, 1);
});
2
répondu Gudradain 2014-11-17 21:45:40

votre code aura des intervalles d'exécution différents, et dans certains projets, tels que les jeux en ligne, ce n'est pas acceptable. Tout d'abord, que devez-vous faire, pour faire fonctionner votre code avec les mêmes intevals, vous devez changer "myTimeoutFunction" à ceci:

function myTimeoutFunction()
{
    setTimeout(myTimeoutFunction, 1000);
    doStuff();
}
myTimeoutFunction()

Après ce changement, il sera égal à

function myTimeoutFunction()
{
    doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

mais, vous n'aurez toujours pas de résultat stable, parce que JS est mono-threadé. Pour l'instant, si js thread va être occupé avec quelque chose, il ne sera pas en mesure d'exécuter votre fonction de rappel, et l'exécution sera reportée pour 2-3 msec. Est vous avez 60 exécutions par seconde, et chaque fois que vous avez aléatoire 1-3 sec de retard, il sera absolument pas acceptable (au bout d'une minute, il sera d'environ 7200 ms de retard), et je peut vous conseiller d'utiliser quelque chose comme ceci:

    function Timer(clb, timeout) {
        this.clb = clb;
        this.timeout = timeout;
        this.stopTimeout = null;
        this.precision = -1;
    }

    Timer.prototype.start = function() {
        var me = this;
        var now = new Date();
        if(me.precision === -1) {
            me.precision = now.getTime();
        }
        me.stopTimeout = setTimeout(function(){
            me.start()
        }, me.precision - now.getTime() + me.timeout);
        me.precision += me.timeout;
        me.clb();
    };

    Timer.prototype.stop = function() {
        clearTimeout(this.stopTimeout);
        this.precision = -1;
    };

    function myTimeoutFunction()
    {
        doStuff();
    }

    var timer = new Timer(myTimeoutFunction, 1000);
    timer.start();

ce code garantit une période d'exécution stable. Même le thread sera occupé, et votre code sera exécuté après 1005 msecondes, la prochaine fois il aura un temps mort pour 995 msec, et le résultat sera stable.

2
répondu degr 2016-12-24 11:32:08

ne fait qu'ajouter à ce qui a déjà été dit, mais la version setTimeout du code atteindra également le Maximum call stack size qui l'empêchera de fonctionner. Puisqu'il n'y a pas de base pour que la fonction récursive s'arrête à donc vous ne pouvez pas la faire tourner pour toujours.

1
répondu Maaz 2014-05-26 15:43:34

il serait probablement préférable de remplacer la première fonction par cette

Options'

function myTimeoutFunction()
{
     setTimeout(myTimeoutFunction, 1000);// At first 
     doStuff();
}
myTimeoutFunction();

N'est-ce pas ?

0
répondu Julien de Prabère 2012-01-22 21:15:58

je pense que SetInterval et SetTimeout sont différents. SetInterval exécute le bloc en fonction de l'heure définie tandis que SetTimeout exécute le bloc de code une fois.

essayez ces codes après les secondes de Compte à rebours:

setInterval(function(e){
    alert('Ugbana Kelvin');
}, 2000);

et ensuite essayer

setTimeout(function(e){
    alert('Ugbana Kelvin');
}, 2000);

Vous pouvez voir les différences pour vous-même.

-5
répondu Ugbana Chukwujindu Kelvin 2013-04-17 02:41:50